mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2026-11-07 17:43:04 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49974403f7 | ||
|
|
7f0026b090 |
No files matched your search
@@ -59,11 +59,9 @@ jobs:
|
||||
working-directory: examples/simple/
|
||||
# - run: go run . # Temporarily disabled very flaky in github actions
|
||||
# working-directory: examples/advanced/
|
||||
|
||||
# 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/
|
||||
- name: "with Speed Control"
|
||||
run: go run .
|
||||
working-directory: examples/with_speed_control/
|
||||
|
||||
integration:
|
||||
name: "Integration tests"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Build
|
||||
FROM golang:1.24-alpine AS builder
|
||||
FROM golang:1.23-alpine AS builder
|
||||
|
||||
RUN apk add build-base
|
||||
WORKDIR /app
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@@ -91,8 +90,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") {
|
||||
@@ -211,7 +210,7 @@ func execute(testCase testutils.TestCase, templatePath string) (string, error) {
|
||||
}
|
||||
|
||||
func expectResultsCount(results []string, expectedNumbers ...int) error {
|
||||
results = filterLines(results)
|
||||
results = filterHeadlessLogs(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
|
||||
@@ -225,13 +224,6 @@ 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 {
|
||||
@@ -245,16 +237,3 @@ 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
|
||||
}
|
||||
@@ -68,21 +68,17 @@ 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{ExecutionId: defaultOpts.ExecutionId}, "", false)
|
||||
reportingClient, err := reporting.New(&reporting.Options{}, "", 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
|
||||
|
||||
@@ -104,7 +100,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,
|
||||
@@ -120,7 +116,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)
|
||||
}
|
||||
@@ -132,7 +128,7 @@ func executeNucleiAsLibrary(templatePath, templateURL string) ([]string, error)
|
||||
}
|
||||
store.Load()
|
||||
|
||||
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(defaultOpts.ExecutionId, templateURL))
|
||||
_ = engine.Execute(context.Background(), store.Templates(), provider.NewSimpleInputProviderWithUrls(templateURL))
|
||||
engine.WorkPool().Wait() // Wait for the scan to finish
|
||||
|
||||
return results, nil
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -16,7 +16,7 @@ var profileLoaderTestcases = []TestCaseInfo{
|
||||
type profileLoaderByRelFile struct{}
|
||||
|
||||
func (h *profileLoaderByRelFile) Execute(testName string) error {
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(debug, "-tl", "-tp", "cloud.yml")
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-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(debug, "-tl", "-tp", "cloud")
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-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(debug, "-tl", "-tp", filepath)
|
||||
results, err := testutils.RunNucleiWithArgsAndGetResults(false, "-tl", "-tp", filepath)
|
||||
if err != nil {
|
||||
return errorutil.NewWithErr(err).Msgf("failed to load template with id")
|
||||
}
|
||||
|
||||
+66
-69
@@ -13,15 +13,14 @@ 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"
|
||||
@@ -53,18 +52,16 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
options.Logger = gologger.DefaultLogger
|
||||
|
||||
// enables CLI specific configs mostly interactive behavior
|
||||
config.CurrentAppMode = config.AppModeCLI
|
||||
|
||||
if err := runner.ConfigureOptions(); err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not initialize options: %s\n", err)
|
||||
}
|
||||
_ = readConfig()
|
||||
|
||||
if options.ListDslSignatures {
|
||||
options.Logger.Info().Msgf("The available custom DSL functions are:")
|
||||
gologger.Info().Msgf("The available custom DSL functions are:")
|
||||
fmt.Println(dsl.GetPrintableDslFunctionSignatures(options.NoColor))
|
||||
return
|
||||
}
|
||||
@@ -75,7 +72,7 @@ func main() {
|
||||
templates.UseOptionsForSigner(options)
|
||||
tsigner, err := signer.NewTemplateSigner(nil, nil) // will read from env , config or generate new keys
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("couldn't initialize signer crypto engine: %s\n", err)
|
||||
gologger.Fatal().Msgf("couldn't initialize signer crypto engine: %s\n", err)
|
||||
}
|
||||
|
||||
successCounter := 0
|
||||
@@ -91,7 +88,7 @@ func main() {
|
||||
if err != templates.ErrNotATemplate {
|
||||
// skip warnings and errors as given items are not templates
|
||||
errorCounter++
|
||||
options.Logger.Error().Msgf("could not sign '%s': %s\n", iterItem, err)
|
||||
gologger.Error().Msgf("could not sign '%s': %s\n", iterItem, err)
|
||||
}
|
||||
} else {
|
||||
successCounter++
|
||||
@@ -100,10 +97,10 @@ func main() {
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
options.Logger.Error().Msgf("%s\n", err)
|
||||
gologger.Error().Msgf("%s\n", err)
|
||||
}
|
||||
}
|
||||
options.Logger.Info().Msgf("All templates signatures were elaborated success=%d failed=%d\n", successCounter, errorCounter)
|
||||
gologger.Info().Msgf("All templates signatures were elaborated success=%d failed=%d\n", successCounter, errorCounter)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,7 +111,7 @@ func main() {
|
||||
createProfileFile := func(ext, profileType string) *os.File {
|
||||
f, err := os.Create(memProfile + ext)
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err)
|
||||
gologger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
@@ -128,18 +125,18 @@ func main() {
|
||||
|
||||
// Start tracing
|
||||
if err := trace.Start(traceFile); err != nil {
|
||||
options.Logger.Fatal().Msgf("profile: could not start trace: %v", err)
|
||||
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
|
||||
}
|
||||
|
||||
// Start CPU profiling
|
||||
if err := pprof.StartCPUProfile(cpuProfileFile); err != nil {
|
||||
options.Logger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
|
||||
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// Start heap memory snapshot
|
||||
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
|
||||
options.Logger.Fatal().Msgf("profile: could not write memory profile: %v", err)
|
||||
gologger.Fatal().Msgf("profile: could not write memory profile: %v", err)
|
||||
}
|
||||
|
||||
pprof.StopCPUProfile()
|
||||
@@ -149,26 +146,24 @@ func main() {
|
||||
|
||||
runtime.MemProfileRate = oldMemProfileRate
|
||||
|
||||
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())
|
||||
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.ExecutionId = xid.New().String()
|
||||
|
||||
runner.ParseOptions(options)
|
||||
|
||||
if options.ScanUploadFile != "" {
|
||||
if err := runner.UploadResultsToCloud(options); err != nil {
|
||||
options.Logger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err)
|
||||
gologger.Fatal().Msgf("could not upload scan results to cloud dashboard: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
nucleiRunner, err := runner.New(options)
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not create runner: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not create runner: %s\n", err)
|
||||
}
|
||||
if nucleiRunner == nil {
|
||||
return
|
||||
@@ -181,10 +176,10 @@ func main() {
|
||||
stackMonitor.RegisterCallback(func(dumpID string) error {
|
||||
resumeFileName := fmt.Sprintf("crash-resume-file-%s.dump", dumpID)
|
||||
if options.EnableCloudUpload {
|
||||
options.Logger.Info().Msgf("Uploading scan results to cloud...")
|
||||
gologger.Info().Msgf("Uploading scan results to cloud...")
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
options.Logger.Info().Msgf("Creating resume file: %s\n", resumeFileName)
|
||||
gologger.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")
|
||||
@@ -196,35 +191,37 @@ func main() {
|
||||
// Setup graceful exits
|
||||
resumeFileName := types.DefaultResumeFilePath()
|
||||
c := make(chan os.Signal, 1)
|
||||
defer close(c)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
<-c
|
||||
options.Logger.Info().Msgf("CTRL+C pressed: Exiting\n")
|
||||
if options.DASTServer {
|
||||
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...")
|
||||
}
|
||||
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 {
|
||||
options.Logger.Fatal().Msgf("Could not validate templates: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not validate templates: %s\n", err)
|
||||
} else {
|
||||
options.Logger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not run nuclei: %s\n", err)
|
||||
}
|
||||
}
|
||||
nucleiRunner.Close()
|
||||
@@ -545,11 +542,11 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
h := &pdcp.PDCPCredHandler{}
|
||||
_, err := h.GetCreds()
|
||||
if err != nil {
|
||||
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.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.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||||
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
|
||||
|
||||
if options.VerboseVerbose {
|
||||
// hide release notes if silent mode is enabled
|
||||
@@ -573,11 +570,11 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
}
|
||||
if cfgFile != "" {
|
||||
if !fileutil.FileExists(cfgFile) {
|
||||
options.Logger.Fatal().Msgf("given config file '%s' does not exist", cfgFile)
|
||||
gologger.Fatal().Msgf("given config file '%s' does not exist", cfgFile)
|
||||
}
|
||||
// merge config file with flags
|
||||
if err := flagSet.MergeConfigFile(cfgFile); err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not read config: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not read config: %s\n", err)
|
||||
}
|
||||
}
|
||||
if options.NewTemplatesDirectory != "" {
|
||||
@@ -590,7 +587,7 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
if tp := findProfilePathById(templateProfile, defaultProfilesPath); tp != "" {
|
||||
templateProfile = tp
|
||||
} else {
|
||||
options.Logger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile)
|
||||
gologger.Fatal().Msgf("'%s' is not a profile-id or profile path", templateProfile)
|
||||
}
|
||||
}
|
||||
if !filepath.IsAbs(templateProfile) {
|
||||
@@ -605,17 +602,17 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
|
||||
}
|
||||
}
|
||||
if !fileutil.FileExists(templateProfile) {
|
||||
options.Logger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile)
|
||||
gologger.Fatal().Msgf("given template profile file '%s' does not exist", templateProfile)
|
||||
}
|
||||
if err := flagSet.MergeConfigFile(templateProfile); err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not read template profile: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not read template profile: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(options.SecretsFile) > 0 {
|
||||
for _, secretFile := range options.SecretsFile {
|
||||
if !fileutil.FileExists(secretFile) {
|
||||
options.Logger.Fatal().Msgf("given secrets file '%s' does not exist", secretFile)
|
||||
gologger.Fatal().Msgf("given secrets file '%s' does not exist", options.SecretsFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,25 +638,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
|
||||
options.Logger.Warning().Msgf("Could not read config file: %s\n", err)
|
||||
gologger.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
|
||||
options.Logger.Warning().Msgf("missing default config file : %s", defaultCfgFile)
|
||||
gologger.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 {
|
||||
options.Logger.Warning().Msgf("Could not copy config file: %s\n", err)
|
||||
gologger.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 {
|
||||
options.Logger.Warning().Msgf("failed to merge configfile with flags got: %s\n", err)
|
||||
gologger.Warning().Msgf("failed to merge configfile with flags got: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,29 +667,29 @@ func disableUpdatesCallback() {
|
||||
|
||||
// printVersion prints the nuclei version and exits.
|
||||
func printVersion() {
|
||||
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)
|
||||
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)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// printTemplateVersion prints the nuclei template version and exits.
|
||||
func printTemplateVersion() {
|
||||
cfg := config.DefaultConfig
|
||||
options.Logger.Info().Msgf("Public nuclei-templates version: %s (%s)\n", cfg.TemplateVersion, cfg.TemplatesDirectory)
|
||||
gologger.Info().Msgf("Public nuclei-templates version: %s (%s)\n", cfg.TemplateVersion, cfg.TemplatesDirectory)
|
||||
|
||||
if fileutil.FolderExists(cfg.CustomS3TemplatesDirectory) {
|
||||
options.Logger.Info().Msgf("Custom S3 templates location: %s\n", cfg.CustomS3TemplatesDirectory)
|
||||
gologger.Info().Msgf("Custom S3 templates location: %s\n", cfg.CustomS3TemplatesDirectory)
|
||||
}
|
||||
if fileutil.FolderExists(cfg.CustomGitHubTemplatesDirectory) {
|
||||
options.Logger.Info().Msgf("Custom GitHub templates location: %s ", cfg.CustomGitHubTemplatesDirectory)
|
||||
gologger.Info().Msgf("Custom GitHub templates location: %s ", cfg.CustomGitHubTemplatesDirectory)
|
||||
}
|
||||
if fileutil.FolderExists(cfg.CustomGitLabTemplatesDirectory) {
|
||||
options.Logger.Info().Msgf("Custom GitLab templates location: %s ", cfg.CustomGitLabTemplatesDirectory)
|
||||
gologger.Info().Msgf("Custom GitLab templates location: %s ", cfg.CustomGitLabTemplatesDirectory)
|
||||
}
|
||||
if fileutil.FolderExists(cfg.CustomAzureTemplatesDirectory) {
|
||||
options.Logger.Info().Msgf("Custom Azure templates location: %s ", cfg.CustomAzureTemplatesDirectory)
|
||||
gologger.Info().Msgf("Custom Azure templates location: %s ", cfg.CustomAzureTemplatesDirectory)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
@@ -708,13 +705,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)
|
||||
options.Logger.Print().Msg(warning)
|
||||
gologger.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 {
|
||||
options.Logger.Fatal().Msgf("could not read response: %s", err)
|
||||
gologger.Fatal().Msgf("could not read response: %s", err)
|
||||
}
|
||||
resp = strings.TrimSpace(resp)
|
||||
if stringsutil.EqualFoldAny(resp, "y", "yes") {
|
||||
@@ -727,13 +724,13 @@ Note: Make sure you have backup of your custom nuclei-templates before proceedin
|
||||
}
|
||||
err := os.RemoveAll(config.DefaultConfig.GetConfigDir())
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("could not delete config dir: %s", err)
|
||||
gologger.Fatal().Msgf("could not delete config dir: %s", err)
|
||||
}
|
||||
err = os.RemoveAll(config.DefaultConfig.TemplatesDirectory)
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("could not delete templates dir: %s", err)
|
||||
gologger.Fatal().Msgf("could not delete templates dir: %s", err)
|
||||
}
|
||||
options.Logger.Info().Msgf("Successfully deleted all nuclei configurations files and nuclei-templates")
|
||||
gologger.Info().Msgf("Successfully deleted all nuclei configurations files and nuclei-templates")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -753,7 +750,7 @@ func findProfilePathById(profileId, templatesDir string) string {
|
||||
return nil
|
||||
})
|
||||
if err != nil && err.Error() != "FOUND" {
|
||||
options.Logger.Error().Msgf("%s\n", err)
|
||||
gologger.Error().Msgf("%s\n", err)
|
||||
}
|
||||
return profilePath
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ var (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// Set up
|
||||
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
|
||||
_ = os.Setenv("DISABLE_STDOUT", "true")
|
||||
|
||||
@@ -92,8 +93,6 @@ func getDefaultOptions() *types.Options {
|
||||
LoadHelperFileFunction: types.DefaultOptions().LoadHelperFileFunction,
|
||||
// DialerKeepAlive: time.Duration(0),
|
||||
// DASTServerAddress: "localhost:9055",
|
||||
ExecutionId: "test",
|
||||
Logger: gologger.DefaultLogger,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -17,15 +17,15 @@ 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 v1.0.8
|
||||
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.2
|
||||
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.103
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.118
|
||||
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
|
||||
@@ -35,11 +35,11 @@ require (
|
||||
github.com/spf13/cast v1.9.2
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/valyala/fasttemplate v1.2.2
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/net v0.42.0
|
||||
golang.org/x/net v0.41.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/text v0.27.0
|
||||
golang.org/x/text v0.26.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
@@ -50,8 +50,7 @@ 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/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697
|
||||
github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/alitto/pond v1.9.2
|
||||
github.com/antchfx/xmlquery v1.4.4
|
||||
github.com/antchfx/xpath v1.3.4
|
||||
@@ -61,16 +60,17 @@ 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.14.0
|
||||
github.com/bytedance/sonic v1.13.3
|
||||
github.com/cespare/xxhash v1.1.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-20250630131328-58d95d85e994
|
||||
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
|
||||
@@ -97,28 +97,31 @@ 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.1-0.20250806055928-39d76476fddf
|
||||
github.com/projectdiscovery/httpx v1.7.0
|
||||
github.com/projectdiscovery/mapcidr v1.1.34
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
|
||||
github.com/projectdiscovery/networkpolicy v0.1.18
|
||||
github.com/projectdiscovery/networkpolicy v0.1.17
|
||||
github.com/projectdiscovery/ratelimit v0.0.81
|
||||
github.com/projectdiscovery/rdap v0.9.0
|
||||
github.com/projectdiscovery/sarif v0.0.1
|
||||
github.com/projectdiscovery/tlsx v1.2.0
|
||||
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.22
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.38
|
||||
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/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/term v0.33.0
|
||||
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
|
||||
)
|
||||
@@ -171,7 +174,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.3.0 // 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
|
||||
@@ -181,7 +184,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.6 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 // 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
|
||||
@@ -191,17 +194,18 @@ 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
|
||||
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.18.0 // 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.8 // indirect
|
||||
github.com/gaissmai/bart v0.20.5 // indirect
|
||||
github.com/gaissmai/bart v0.20.4 // indirect
|
||||
github.com/geoffgarside/ber v1.1.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
@@ -215,28 +219,33 @@ 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.4.0 // 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.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
|
||||
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.3.2 // 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.8 // 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.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.16 // 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
|
||||
@@ -281,8 +290,6 @@ 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
|
||||
@@ -296,11 +303,13 @@ 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.28 // 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.7.1 // 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
|
||||
@@ -334,52 +343,33 @@ 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/got v0.40.0 // 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
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||
golang.org/x/arch v0.3.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
|
||||
)
|
||||
|
||||
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/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
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // 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.40.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||
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/sys v0.34.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
|
||||
golang.org/x/tools v0.34.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
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/go-echarts/go-echarts/v2 v2.6.0
|
||||
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
mellium.im/sasl v0.3.2 // indirect
|
||||
)
|
||||
|
||||
// https://go.dev/ref/mod#go-mod-file-retract
|
||||
|
||||
@@ -83,10 +83,6 @@ 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=
|
||||
@@ -191,6 +187,8 @@ 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=
|
||||
@@ -214,11 +212,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.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||
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.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||
github.com/bytedance/sonic/loader v0.3.0/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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
@@ -247,8 +245,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.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk=
|
||||
github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s=
|
||||
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=
|
||||
@@ -301,8 +299,8 @@ 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-20250630131328-58d95d85e994 h1:aQYWswi+hRL2zJqGacdCZx32XjKYV8ApXFGntw79XAM=
|
||||
github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4=
|
||||
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=
|
||||
@@ -317,8 +315,8 @@ 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.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
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=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||
@@ -334,8 +332,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gaissmai/bart v0.20.5 h1:ehoWZWQ7j//qt0K0Zs4i9hpoPpbgqsMQiR8W2QPJh+c=
|
||||
github.com/gaissmai/bart v0.20.5/go.mod h1:cEed+ge8dalcbpi8wtS9x9m2hn/fNJH5suhdGQOHnYk=
|
||||
github.com/gaissmai/bart v0.20.4 h1:Ik47r1fy3jRVU+1eYzKSW3ho2UgBVTVnUS8O993584U=
|
||||
github.com/gaissmai/bart v0.20.4/go.mod h1:cEed+ge8dalcbpi8wtS9x9m2hn/fNJH5suhdGQOHnYk=
|
||||
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
|
||||
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
|
||||
github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
|
||||
@@ -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.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/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=
|
||||
@@ -461,8 +459,8 @@ 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/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/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/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=
|
||||
@@ -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.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
||||
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-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.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
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=
|
||||
@@ -654,6 +652,7 @@ 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=
|
||||
@@ -715,12 +714,8 @@ 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 v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ=
|
||||
github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
|
||||
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=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
@@ -765,14 +760,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.28 h1:Nn+9SuB4Xv56lFn5zN5hWB0Kq/5veAUX0xnRb+K+IeM=
|
||||
github.com/projectdiscovery/cdncheck v1.1.28/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.5.0 h1:3HHY14FNmdwWXq3pi9dd8JjUHQzskZjLD/pZKVx5Vi4=
|
||||
github.com/projectdiscovery/dsl v0.5.0/go.mod h1:Fr+zIQJfMNy+RTj5KFgozfvDaiQQEKMyrKXl75aGgxY=
|
||||
github.com/projectdiscovery/fastdialer v0.4.2 h1:uB+p8CinbrzlAwfGeTyHKShjnYBj60rcZ8FoBtGlg7I=
|
||||
github.com/projectdiscovery/fastdialer v0.4.2/go.mod h1:g3ikfujsn3g+ZdyypNpMzMTj2qHHXXqjZL9YioX53Ok=
|
||||
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=
|
||||
@@ -791,8 +786,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.91 h1:8vSTU+3hmMfA5Qd14ceq4j7wnUVUJcXdqQgqbsFBea0=
|
||||
github.com/projectdiscovery/hmap v0.0.91/go.mod h1:BxEg8WXqxqaOADPZ+xp2X6BY+znfV8dusCSGSFnsU3c=
|
||||
github.com/projectdiscovery/httpx v1.7.1-0.20250806055928-39d76476fddf h1:4BSaCK8/h8XH2qZuxllh5WLULpY5c8/EmKCs6lR0V/k=
|
||||
github.com/projectdiscovery/httpx v1.7.1-0.20250806055928-39d76476fddf/go.mod h1:fSaOSbW/YyyCn9rBS3aP99C0KuCrD/O1/ITPjoaLBR8=
|
||||
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=
|
||||
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=
|
||||
@@ -803,8 +798,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.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=
|
||||
@@ -813,22 +808,22 @@ 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.118 h1:ylbb2mKOfFQOwbtGyI1C0yzudl/UvJvC9YbWIPMyXQY=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.0.118/go.mod h1:pAQWFh6lg9Gmno5zrQxbfuAbc9OvIugl5P9kaoXztgM=
|
||||
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.2.0 h1:n92B+ZAIzWW3+UFOJpI4ILWZuDcQHHLwVqbWXnZPJdc=
|
||||
github.com/projectdiscovery/tlsx v1.2.0/go.mod h1:ddPZIluCZBN4N0nn+H0f/QjimF7MOhpQ5RXkJ7zZnwA=
|
||||
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.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.22 h1:OO3FU2uX967sQxu5JtpdBZNzOevvKHAhWqkoTGl+C0A=
|
||||
github.com/projectdiscovery/utils v0.4.22/go.mod h1:3l84gpCwL9KG1/ZmslOBABCrk84CcpGWJZfR8wZysR4=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.38 h1:R7gf5NlndtKd2OFT34uIgFlXDJzE8MXRIwQandAC40M=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.38/go.mod h1:XQSgnMQnxliVw2wjKehxeJ4QTRluOJpmm55gLHdztVQ=
|
||||
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=
|
||||
@@ -857,8 +852,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
|
||||
github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/refraction-networking/utls v1.7.1 h1:dxg+jla3uocgN8HtX+ccwDr68uCBBO3qLrkZUbqkcw0=
|
||||
github.com/refraction-networking/utls v1.7.1/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
|
||||
github.com/refraction-networking/utls v1.7.0 h1:9JTnze/Md74uS3ZWiRAabityY0un69rOLXsBf8LGgTs=
|
||||
github.com/refraction-networking/utls v1.7.0/go.mod h1:lV0Gwc1/Fi+HYH8hOtgFRdHfKo4FKSn6+FdyOz9hRms=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -978,8 +973,8 @@ github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8L
|
||||
github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY=
|
||||
github.com/weppos/publicsuffix-go v0.30.2/go.mod h1:/hGscit36Yt+wammfBBwdMdxBT8btsTt6KvwO9OvMyM=
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39 h1:Bz/zVM/LoGZ9IztGBHrq2zlFQQbEG8dBYnxb4hamIHM=
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250408071509-6074bbe7fd39/go.mod h1:2oFzEwGYI7lhiqG0YkkcKa6VcpjVinQbWxaPzytDmLA=
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b h1:PFOWooJRLwIuZk9i3ihzKzZffPrAVyOCzPInvLbn140=
|
||||
github.com/weppos/publicsuffix-go v0.40.3-0.20250311103038-7794c8c0723b/go.mod h1:EACzvcFHnxqmDapI/oqMjtpXz+mtjNzJe7r1zhRczZ0=
|
||||
github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
@@ -1032,8 +1027,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
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.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
|
||||
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
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=
|
||||
@@ -1062,8 +1057,8 @@ 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.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.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=
|
||||
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=
|
||||
@@ -1075,8 +1070,8 @@ 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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
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=
|
||||
@@ -1106,8 +1101,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.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
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=
|
||||
@@ -1197,8 +1192,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.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
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=
|
||||
@@ -1227,8 +1222,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.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
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=
|
||||
@@ -1293,8 +1288,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.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.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=
|
||||
@@ -1308,8 +1303,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.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
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=
|
||||
@@ -1326,8 +1321,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.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
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=
|
||||
@@ -1496,6 +1491,7 @@ 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=
|
||||
|
||||
+13
-15
@@ -55,11 +55,10 @@ type UploadWriter struct {
|
||||
scanName string
|
||||
counter atomic.Int32
|
||||
TeamID string
|
||||
Logger *gologger.Logger
|
||||
}
|
||||
|
||||
// NewUploadWriter creates a new upload writer
|
||||
func NewUploadWriter(ctx context.Context, logger *gologger.Logger, creds *pdcpauth.PDCPCredentials) (*UploadWriter, error) {
|
||||
func NewUploadWriter(ctx context.Context, creds *pdcpauth.PDCPCredentials) (*UploadWriter, error) {
|
||||
if creds == nil {
|
||||
return nil, fmt.Errorf("no credentials provided")
|
||||
}
|
||||
@@ -67,7 +66,6 @@ func NewUploadWriter(ctx context.Context, logger *gologger.Logger, creds *pdcpau
|
||||
creds: creds,
|
||||
done: make(chan struct{}, 1),
|
||||
TeamID: NoneTeamID,
|
||||
Logger: logger,
|
||||
}
|
||||
var err error
|
||||
reader, writer := io.Pipe()
|
||||
@@ -130,8 +128,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')
|
||||
@@ -149,9 +147,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 == "" {
|
||||
u.Logger.Verbose().Msgf("Scan results upload to cloud skipped, no results found to upload")
|
||||
gologger.Verbose().Msgf("Scan results upload to cloud skipped, no results found to upload")
|
||||
} else {
|
||||
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))
|
||||
gologger.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
|
||||
@@ -164,7 +162,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 {
|
||||
u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -172,14 +170,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 {
|
||||
u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
gologger.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 {
|
||||
u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -187,7 +185,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 {
|
||||
u.Logger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
gologger.Error().Msgf("Failed to upload scan results on cloud: %v", err)
|
||||
}
|
||||
} else {
|
||||
buff.WriteString(line)
|
||||
@@ -204,7 +202,7 @@ func (u *UploadWriter) uploadChunk(buff *bytes.Buffer) error {
|
||||
// if successful, reset the buffer
|
||||
buff.Reset()
|
||||
// log in verbose mode
|
||||
u.Logger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID, u.TeamID))
|
||||
gologger.Warning().Msgf("Uploaded results chunk, you can view scan results at %v", getScanDashBoardURL(u.scanID, u.TeamID))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -218,8 +216,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")
|
||||
@@ -262,7 +260,7 @@ func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) {
|
||||
if u.scanName != "" && req.Path == uploadEndpoint {
|
||||
req.Params.Add("name", u.scanName)
|
||||
}
|
||||
req.Update()
|
||||
req.URL.Update()
|
||||
|
||||
req.Header.Set(pdcpauth.ApiKeyHeaderName, u.creds.APIKey)
|
||||
if u.TeamID != NoneTeamID && u.TeamID != "" {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
r.Logger.Info().Msgf("Running httpx on input host")
|
||||
gologger.Info().Msgf("Running httpx on input host")
|
||||
|
||||
httpxOptions := httpx.DefaultOptions
|
||||
if r.options.AliveHttpProxy != "" {
|
||||
@@ -38,13 +38,7 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
|
||||
}
|
||||
httpxOptions.RetryMax = r.options.Retries
|
||||
httpxOptions.Timeout = time.Duration(r.options.Timeout) * time.Second
|
||||
|
||||
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
|
||||
httpxOptions.NetworkPolicy = protocolstate.NetworkPolicy
|
||||
httpxClient, err := httpx.New(&httpxOptions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not create httpx client")
|
||||
@@ -63,7 +57,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 {
|
||||
r.Logger.Error().Msgf("Could not resize workpool: %s\n", err)
|
||||
gologger.Error().Msgf("Could not resize workpool: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +74,6 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
|
||||
})
|
||||
swg.Wait()
|
||||
|
||||
r.Logger.Info().Msgf("Found %d URL from httpx", count.Load())
|
||||
gologger.Info().Msgf("Found %d URL from httpx", count.Load())
|
||||
return hm, nil
|
||||
}
|
||||
@@ -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 *pr
|
||||
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 {
|
||||
|
||||
+30
-31
@@ -31,6 +31,7 @@ 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"
|
||||
)
|
||||
|
||||
@@ -39,8 +40,6 @@ 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
|
||||
@@ -72,17 +71,17 @@ func ParseOptions(options *types.Options) {
|
||||
vardump.Limit = options.VarDumpLimit
|
||||
}
|
||||
if options.ShowActions {
|
||||
options.Logger.Info().Msgf("Showing available headless actions: ")
|
||||
gologger.Info().Msgf("Showing available headless actions: ")
|
||||
for action := range engine.ActionStringToAction {
|
||||
options.Logger.Print().Msgf("\t%s", action)
|
||||
gologger.Print().Msgf("\t%s", action)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
defaultProfilesPath := filepath.Join(config.DefaultConfig.GetTemplateDir(), "profiles")
|
||||
if options.ListTemplateProfiles {
|
||||
options.Logger.Print().Msgf(
|
||||
"Listing available %v nuclei template profiles for %v",
|
||||
gologger.Print().Msgf(
|
||||
"\nListing available %v nuclei template profiles for %v",
|
||||
config.DefaultConfig.TemplateVersion,
|
||||
config.DefaultConfig.TemplatesDirectory,
|
||||
)
|
||||
@@ -94,23 +93,23 @@ func ParseOptions(options *types.Options) {
|
||||
return nil
|
||||
}
|
||||
if profileRelPath, err := filepath.Rel(templatesRootDir, iterItem); err == nil {
|
||||
options.Logger.Print().Msgf("%s (%s)\n", profileRelPath, strings.TrimSuffix(filepath.Base(iterItem), ext))
|
||||
gologger.Print().Msgf("%s (%s)\n", profileRelPath, strings.TrimSuffix(filepath.Base(iterItem), ext))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
options.Logger.Error().Msgf("%s\n", err)
|
||||
gologger.Error().Msgf("%s\n", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
if options.StoreResponseDir != DefaultDumpTrafficOutputFolder && !options.StoreResponse {
|
||||
options.Logger.Debug().Msgf("Store response directory specified, enabling \"store-resp\" flag automatically\n")
|
||||
gologger.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 {
|
||||
options.Logger.Fatal().Msgf("Program exiting: %s\n", err)
|
||||
gologger.Fatal().Msgf("Program exiting: %s\n", err)
|
||||
}
|
||||
|
||||
// Load the resolvers if user asked for them
|
||||
@@ -118,7 +117,7 @@ func ParseOptions(options *types.Options) {
|
||||
|
||||
err := protocolinit.Init(options)
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not initialize protocols: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err)
|
||||
}
|
||||
|
||||
// Set GitHub token in env variable. runner.getGHClientWithToken() reads token from env
|
||||
@@ -140,7 +139,8 @@ func ParseOptions(options *types.Options) {
|
||||
|
||||
// validateOptions validates the configuration options passed
|
||||
func ValidateOptions(options *types.Options) error {
|
||||
if err := validateOptions.Struct(options); err != nil {
|
||||
validate := validator.New()
|
||||
if err := validate.Struct(options); err != nil {
|
||||
if _, ok := err.(*validator.InvalidValidationError); ok {
|
||||
return err
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func ValidateOptions(options *types.Options) error {
|
||||
return err
|
||||
}
|
||||
if options.Validate {
|
||||
validateTemplatePaths(options.Logger, config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows)
|
||||
validateTemplatePaths(config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows)
|
||||
}
|
||||
if options.DAST {
|
||||
if err := validateDASTOptions(options); err != nil {
|
||||
@@ -182,7 +182,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.Logger, options.ClientCertFile, options.ClientKeyFile, options.ClientCAFile)
|
||||
validateCertificatePaths(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 +305,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,33 +344,32 @@ 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 {
|
||||
options.Logger.SetFormatter(formatter.NewCLI(true))
|
||||
gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true))
|
||||
}
|
||||
// If the user desires verbose output, show verbose output
|
||||
if options.Debug || options.DebugRequests || options.DebugResponse {
|
||||
options.Logger.SetMaxLevel(levels.LevelDebug)
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug)
|
||||
}
|
||||
// Debug takes precedence before verbose
|
||||
// because debug is a lower logging level.
|
||||
if options.Verbose || options.Validate {
|
||||
options.Logger.SetMaxLevel(levels.LevelVerbose)
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
|
||||
}
|
||||
if options.NoColor {
|
||||
options.Logger.SetFormatter(formatter.NewCLI(true))
|
||||
gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true))
|
||||
}
|
||||
if options.Silent {
|
||||
options.Logger.SetMaxLevel(levels.LevelSilent)
|
||||
gologger.DefaultLogger.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
|
||||
@@ -381,11 +380,11 @@ func loadResolvers(options *types.Options) {
|
||||
|
||||
file, err := os.Open(options.ResolversFile)
|
||||
if err != nil {
|
||||
options.Logger.Fatal().Msgf("Could not open resolvers file: %s\n", err)
|
||||
gologger.Fatal().Msgf("Could not open resolvers file: %s\n", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
@@ -401,7 +400,7 @@ func loadResolvers(options *types.Options) {
|
||||
}
|
||||
}
|
||||
|
||||
func validateTemplatePaths(logger *gologger.Logger, templatesDirectory string, templatePaths, workflowPaths []string) {
|
||||
func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPaths []string) {
|
||||
allGivenTemplatePaths := append(templatePaths, workflowPaths...)
|
||||
for _, templatePath := range allGivenTemplatePaths {
|
||||
if templatesDirectory != templatePath && filepath.IsAbs(templatePath) {
|
||||
@@ -409,7 +408,7 @@ func validateTemplatePaths(logger *gologger.Logger, templatesDirectory string, t
|
||||
if err == nil && fileInfo.IsDir() {
|
||||
relativizedPath, err2 := filepath.Rel(templatesDirectory, templatePath)
|
||||
if err2 != nil || (len(relativizedPath) >= 2 && relativizedPath[:2] == "..") {
|
||||
logger.Warning().Msgf("The given path (%s) is outside the default template directory path (%s)! "+
|
||||
gologger.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
|
||||
}
|
||||
@@ -418,12 +417,12 @@ func validateTemplatePaths(logger *gologger.Logger, templatesDirectory string, t
|
||||
}
|
||||
}
|
||||
|
||||
func validateCertificatePaths(logger *gologger.Logger, certificatePaths ...string) {
|
||||
func validateCertificatePaths(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
|
||||
logger.Fatal().Msgf("The given path (%s) to the certificate does not exist!", certificatePath)
|
||||
gologger.Fatal().Msgf("The given path (%s) to the certificate does not exist!", certificatePath)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -450,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 {
|
||||
options.Logger.Warning().Msgf("Invalid GitLab template repository ID: %s", repoID)
|
||||
gologger.Warning().Msgf("Invalid GitLab template repository ID: %s", repoID)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ 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"
|
||||
@@ -30,8 +31,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()
|
||||
@@ -57,11 +58,11 @@ func loadProxyServers(options *types.Options) error {
|
||||
}
|
||||
switch proxyURL.Scheme {
|
||||
case proxyutils.HTTP, proxyutils.HTTPS:
|
||||
options.Logger.Verbose().Msgf("Using %s as proxy server", proxyURL.String())
|
||||
gologger.Verbose().Msgf("Using %s as proxy server", proxyURL.String())
|
||||
options.AliveHttpProxy = proxyURL.String()
|
||||
case proxyutils.SOCKS5:
|
||||
options.AliveSocksProxy = proxyURL.String()
|
||||
options.Logger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String())
|
||||
gologger.Verbose().Msgf("Using %s as socket proxy server", proxyURL.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+56
-66
@@ -10,7 +10,6 @@ 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"
|
||||
@@ -33,6 +32,7 @@ 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,7 +95,6 @@ type Runner struct {
|
||||
inputProvider provider.InputProvider
|
||||
fuzzFrequencyCache *frequency.Tracker
|
||||
httpStats *outputstats.Tracker
|
||||
Logger *gologger.Logger
|
||||
|
||||
//general purpose temporary directory
|
||||
tmpDir string
|
||||
@@ -109,11 +108,10 @@ type Runner struct {
|
||||
func New(options *types.Options) (*Runner, error) {
|
||||
runner := &Runner{
|
||||
options: options,
|
||||
Logger: options.Logger,
|
||||
}
|
||||
|
||||
if options.HealthCheck {
|
||||
runner.Logger.Print().Msgf("%s\n", DoHealthCheck(options))
|
||||
gologger.Print().Msgf("%s\n", DoHealthCheck(options))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
@@ -121,14 +119,14 @@ func New(options *types.Options) (*Runner, error) {
|
||||
if config.DefaultConfig.CanCheckForUpdates() {
|
||||
if err := installer.NucleiVersionCheck(); err != nil {
|
||||
if options.Verbose || options.Debug {
|
||||
runner.Logger.Error().Msgf("nuclei version check failed got: %s\n", err)
|
||||
gologger.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 {
|
||||
runner.Logger.Error().Label("custom-templates").Msgf("Failed to create custom templates manager: %s\n", err)
|
||||
gologger.Error().Label("custom-templates").Msgf("Failed to create custom templates manager: %s\n", err)
|
||||
}
|
||||
|
||||
// Check for template updates and update if available.
|
||||
@@ -138,15 +136,15 @@ func New(options *types.Options) (*Runner, error) {
|
||||
DisablePublicTemplates: options.PublicTemplateDisableDownload,
|
||||
}
|
||||
if err := tm.FreshInstallIfNotExists(); err != nil {
|
||||
runner.Logger.Warning().Msgf("failed to install nuclei templates: %s\n", err)
|
||||
gologger.Warning().Msgf("failed to install nuclei templates: %s\n", err)
|
||||
}
|
||||
if err := tm.UpdateIfOutdated(); err != nil {
|
||||
runner.Logger.Warning().Msgf("failed to update nuclei templates: %s\n", err)
|
||||
gologger.Warning().Msgf("failed to update nuclei templates: %s\n", err)
|
||||
}
|
||||
|
||||
if config.DefaultConfig.NeedsIgnoreFileUpdate() {
|
||||
if err := installer.UpdateIgnoreFile(); err != nil {
|
||||
runner.Logger.Warning().Msgf("failed to update nuclei ignore file: %s\n", err)
|
||||
gologger.Warning().Msgf("failed to update nuclei ignore file: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +152,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() {
|
||||
runner.Logger.Info().Msgf("No new updates found for nuclei templates")
|
||||
gologger.Info().Msgf("No new updates found for nuclei templates")
|
||||
}
|
||||
// manually trigger update of custom templates
|
||||
if ctm != nil {
|
||||
@@ -163,25 +161,20 @@ func New(options *types.Options) (*Runner, error) {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
yaml.StrictSyntax = !options.NoStrictSyntax
|
||||
|
||||
if options.Headless {
|
||||
if engine.MustDisableSandbox() {
|
||||
runner.Logger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n")
|
||||
gologger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n")
|
||||
}
|
||||
browser, err := engine.New(options)
|
||||
if err != nil {
|
||||
@@ -233,11 +226,11 @@ func New(options *types.Options) (*Runner, error) {
|
||||
|
||||
if options.HttpApiEndpoint != "" {
|
||||
apiServer := httpapi.New(options.HttpApiEndpoint, options)
|
||||
runner.Logger.Info().Msgf("Listening api endpoint on: %s", options.HttpApiEndpoint)
|
||||
gologger.Info().Msgf("Listening api endpoint on: %s", options.HttpApiEndpoint)
|
||||
runner.httpApiEndpoint = apiServer
|
||||
go func() {
|
||||
if err := apiServer.Start(); err != nil {
|
||||
runner.Logger.Error().Msgf("Failed to start API server: %s", err)
|
||||
gologger.Error().Msgf("Failed to start API server: %s", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -291,7 +284,7 @@ func New(options *types.Options) (*Runner, error) {
|
||||
// create the resume configuration structure
|
||||
resumeCfg := types.NewResumeCfg()
|
||||
if runner.options.ShouldLoadResume() {
|
||||
runner.Logger.Info().Msg("Resuming from save checkpoint")
|
||||
gologger.Info().Msg("Resuming from save checkpoint")
|
||||
file, err := os.ReadFile(runner.options.Resume)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -333,7 +326,6 @@ 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 != "" {
|
||||
@@ -363,13 +355,13 @@ func New(options *types.Options) (*Runner, error) {
|
||||
}
|
||||
interactshClient, err := interactsh.New(opts)
|
||||
if err != nil {
|
||||
runner.Logger.Error().Msgf("Could not create interactsh client: %s", err)
|
||||
gologger.Error().Msgf("Could not create interactsh client: %s", err)
|
||||
} else {
|
||||
runner.interactsh = interactshClient
|
||||
}
|
||||
|
||||
if options.RateLimitMinute > 0 {
|
||||
runner.Logger.Print().Msgf("[%v] %v", aurora.BrightYellow("WRN"), "rate limit per minute is deprecated - use rate-limit-duration")
|
||||
gologger.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
|
||||
}
|
||||
@@ -390,7 +382,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)
|
||||
}
|
||||
@@ -421,7 +413,7 @@ func (r *Runner) Close() {
|
||||
if r.inputProvider != nil {
|
||||
r.inputProvider.Close()
|
||||
}
|
||||
protocolinit.Close(r.options.ExecutionId)
|
||||
protocolinit.Close()
|
||||
if r.pprofServer != nil {
|
||||
r.pprofServer.Stop()
|
||||
}
|
||||
@@ -448,21 +440,22 @@ func (r *Runner) setupPDCPUpload(writer output.Writer) output.Writer {
|
||||
r.options.EnableCloudUpload = true
|
||||
}
|
||||
if !r.options.EnableCloudUpload && !EnableCloudUpload {
|
||||
r.pdcpUploadErrMsg = "Scan results upload to cloud is disabled."
|
||||
r.pdcpUploadErrMsg = fmt.Sprintf("[%v] Scan results upload to cloud is disabled.", r.colorizer.BrightYellow("WRN"))
|
||||
return writer
|
||||
}
|
||||
color := aurora.NewAurora(!r.options.NoColor)
|
||||
h := &pdcpauth.PDCPCredHandler{}
|
||||
creds, err := h.GetCreds()
|
||||
if err != nil {
|
||||
if err != pdcpauth.ErrNoCreds && !HideAutoSaveMsg {
|
||||
r.Logger.Verbose().Msgf("Could not get credentials for cloud upload: %s\n", err)
|
||||
gologger.Verbose().Msgf("Could not get credentials for cloud upload: %s\n", err)
|
||||
}
|
||||
r.pdcpUploadErrMsg = fmt.Sprintf("To view results on Cloud Dashboard, configure API key from %v", pdcpauth.DashBoardURL)
|
||||
r.pdcpUploadErrMsg = fmt.Sprintf("[%v] To view results on Cloud Dashboard, Configure API key from %v", color.BrightYellow("WRN"), pdcpauth.DashBoardURL)
|
||||
return writer
|
||||
}
|
||||
uploadWriter, err := pdcp.NewUploadWriter(context.Background(), r.Logger, creds)
|
||||
uploadWriter, err := pdcp.NewUploadWriter(context.Background(), creds)
|
||||
if err != nil {
|
||||
r.pdcpUploadErrMsg = fmt.Sprintf("PDCP (%v) Auto-Save Failed: %s\n", pdcpauth.DashBoardURL, err)
|
||||
r.pdcpUploadErrMsg = fmt.Sprintf("[%v] PDCP (%v) Auto-Save Failed: %s\n", color.BrightYellow("WRN"), pdcpauth.DashBoardURL, err)
|
||||
return writer
|
||||
}
|
||||
if r.options.ScanID != "" {
|
||||
@@ -498,7 +491,6 @@ 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,
|
||||
@@ -540,7 +532,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,
|
||||
@@ -558,8 +550,6 @@ 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) {
|
||||
@@ -568,7 +558,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")
|
||||
}
|
||||
@@ -588,8 +578,8 @@ func (r *Runner) RunEnumeration() error {
|
||||
if r.options.ShouldUseHostError() {
|
||||
maxHostError := r.options.MaxHostError
|
||||
if r.options.TemplateThreads > maxHostError {
|
||||
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)
|
||||
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)
|
||||
|
||||
maxHostError = r.options.TemplateThreads
|
||||
}
|
||||
@@ -604,7 +594,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.")
|
||||
}
|
||||
@@ -643,7 +633,7 @@ func (r *Runner) RunEnumeration() error {
|
||||
return err
|
||||
}
|
||||
if stats.GetValue(templates.SyntaxErrorStats) == 0 && stats.GetValue(templates.SyntaxWarningStats) == 0 && stats.GetValue(templates.RuntimeWarningsStats) == 0 {
|
||||
r.Logger.Info().Msgf("All templates validated successfully")
|
||||
gologger.Info().Msgf("All templates validated successfully\n")
|
||||
} else {
|
||||
return errors.New("encountered errors while performing template validation")
|
||||
}
|
||||
@@ -665,7 +655,7 @@ func (r *Runner) RunEnumeration() error {
|
||||
}
|
||||
ret := uncover.GetUncoverTargetsFromMetadata(context.TODO(), store.Templates(), r.options.UncoverField, uncoverOpts)
|
||||
for host := range ret {
|
||||
_ = r.inputProvider.SetWithExclusions(r.options.ExecutionId, host)
|
||||
_ = r.inputProvider.SetWithExclusions(host)
|
||||
}
|
||||
}
|
||||
// display execution info like version , templates used etc
|
||||
@@ -673,7 +663,7 @@ func (r *Runner) RunEnumeration() error {
|
||||
|
||||
// prefetch secrets if enabled
|
||||
if executorOpts.AuthProvider != nil && r.options.PreFetchSecrets {
|
||||
r.Logger.Info().Msgf("Pre-fetching secrets from authprovider[s]")
|
||||
gologger.Info().Msgf("Pre-fetching secrets from authprovider[s]")
|
||||
if err := executorOpts.AuthProvider.PreFetchSecrets(); err != nil {
|
||||
return errors.Wrap(err, "could not pre-fetch secrets")
|
||||
}
|
||||
@@ -707,7 +697,7 @@ func (r *Runner) RunEnumeration() error {
|
||||
if r.dastServer != nil {
|
||||
go func() {
|
||||
if err := r.dastServer.Start(); err != nil {
|
||||
r.Logger.Error().Msgf("could not start dast server: %v", err)
|
||||
gologger.Error().Msgf("could not start dast server: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -741,10 +731,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() {
|
||||
r.Logger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken))
|
||||
gologger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken))
|
||||
} else {
|
||||
matchCount := r.output.ResultCount()
|
||||
r.Logger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount)
|
||||
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
|
||||
@@ -785,7 +775,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{
|
||||
@@ -853,7 +843,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 {
|
||||
r.Logger.Print().Msgf("[%v] No DAST templates found", aurora.BrightYellow("WRN"))
|
||||
gologger.DefaultLogger.Print().Msgf("[%v] No DAST templates found", aurora.BrightYellow("WRN"))
|
||||
}
|
||||
stats.ForceDisplayWarning(templates.SkippedCodeTmplTamperedStats)
|
||||
} else {
|
||||
@@ -877,34 +867,34 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
|
||||
gologger.Info().Msg(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates"))
|
||||
if !HideAutoSaveMsg {
|
||||
if r.pdcpUploadErrMsg != "" {
|
||||
r.Logger.Warning().Msgf("%s", r.pdcpUploadErrMsg)
|
||||
gologger.Print().Msgf("%s", r.pdcpUploadErrMsg)
|
||||
} else {
|
||||
r.Logger.Info().Msgf("To view results on cloud dashboard, visit %v/scans upon scan completion.", pdcpauth.DashBoardURL)
|
||||
gologger.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 {
|
||||
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()))
|
||||
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()))
|
||||
}
|
||||
if len(store.Workflows()) > 0 {
|
||||
r.Logger.Info().Msgf("Workflows loaded for current scan: %d", len(store.Workflows()))
|
||||
gologger.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 {
|
||||
r.Logger.Print().Msgf("[%v] Loading %d unsigned templates for scan. Use with caution.", r.colorizer.BrightYellow("WRN"), value)
|
||||
gologger.Print().Msgf("[%v] Loading %d unsigned templates for scan. Use with caution.", r.colorizer.BrightYellow("WRN"), value)
|
||||
} else {
|
||||
r.Logger.Info().Msgf("Executing %d signed templates from %s", value, k)
|
||||
gologger.Info().Msgf("Executing %d signed templates from %s", value, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r.inputProvider.Count() > 0 {
|
||||
r.Logger.Info().Msgf("Targets loaded for current scan: %d", r.inputProvider.Count())
|
||||
gologger.Info().Msgf("Targets loaded for current scan: %d", r.inputProvider.Count())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,7 +921,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, options.Logger, creds)
|
||||
uploadWriter, err := pdcp.NewUploadWriter(ctx, creds)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not create upload writer")
|
||||
}
|
||||
@@ -951,20 +941,20 @@ func UploadResultsToCloud(options *types.Options) error {
|
||||
return errors.Wrap(err, "could not open scan upload file")
|
||||
}
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
options.Logger.Info().Msgf("Uploading scan results to cloud dashboard from %s", options.ScanUploadFile)
|
||||
gologger.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 {
|
||||
options.Logger.Warning().Msgf("Could not decode jsonl: %s\n", err)
|
||||
gologger.Warning().Msgf("Could not decode jsonl: %s\n", err)
|
||||
continue
|
||||
}
|
||||
if err = uploadWriter.Write(&r); err != nil {
|
||||
options.Logger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err)
|
||||
gologger.Warning().Msgf("[%s] failed to upload: %s\n", r.TemplateID, err)
|
||||
}
|
||||
}
|
||||
uploadWriter.Close()
|
||||
|
||||
@@ -12,6 +12,7 @@ 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"
|
||||
)
|
||||
@@ -24,7 +25,7 @@ func (r *Runner) logAvailableTemplate(tplPath string) {
|
||||
panic("not a template")
|
||||
}
|
||||
if err != nil {
|
||||
r.Logger.Error().Msgf("Could not parse file '%s': %s\n", tplPath, err)
|
||||
gologger.Error().Msgf("Could not parse file '%s': %s\n", tplPath, err)
|
||||
} else {
|
||||
r.verboseTemplate(tpl)
|
||||
}
|
||||
@@ -32,14 +33,14 @@ func (r *Runner) logAvailableTemplate(tplPath string) {
|
||||
|
||||
// log available templates for verbose (-vv)
|
||||
func (r *Runner) verboseTemplate(tpl *templates.Template) {
|
||||
r.Logger.Print().Msgf("%s\n", templates.TemplateLogMessage(tpl.ID,
|
||||
gologger.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) {
|
||||
r.Logger.Print().Msgf(
|
||||
gologger.Print().Msgf(
|
||||
"\nListing available %v nuclei templates for %v",
|
||||
config.DefaultConfig.TemplateVersion,
|
||||
config.DefaultConfig.TemplatesDirectory,
|
||||
@@ -51,20 +52,20 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) {
|
||||
path := tpl.Path
|
||||
tplBody, err := store.ReadTemplateFromURI(path, true)
|
||||
if err != nil {
|
||||
r.Logger.Error().Msgf("Could not read the template %s: %s", path, err)
|
||||
gologger.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 {
|
||||
r.Logger.Error().Msgf("Could not highlight the template %s: %s", tpl.Path, err)
|
||||
gologger.Error().Msgf("Could not highlight the template %s: %s", tpl.Path, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
r.Logger.Print().Msgf("Template: %s\n\n%s", path, tplBody)
|
||||
gologger.Silent().Msgf("Template: %s\n\n%s", path, tplBody)
|
||||
} else {
|
||||
r.Logger.Print().Msgf("%s\n", strings.TrimPrefix(tpl.Path, config.DefaultConfig.TemplatesDirectory+string(filepath.Separator)))
|
||||
gologger.Silent().Msgf("%s\n", strings.TrimPrefix(tpl.Path, config.DefaultConfig.TemplatesDirectory+string(filepath.Separator)))
|
||||
}
|
||||
} else {
|
||||
r.verboseTemplate(tpl)
|
||||
@@ -73,7 +74,7 @@ func (r *Runner) listAvailableStoreTemplates(store *loader.Store) {
|
||||
}
|
||||
|
||||
func (r *Runner) listAvailableStoreTags(store *loader.Store) {
|
||||
r.Logger.Print().Msgf(
|
||||
gologger.Print().Msgf(
|
||||
"\nListing available %v nuclei tags for %v",
|
||||
config.DefaultConfig.TemplateVersion,
|
||||
config.DefaultConfig.TemplatesDirectory,
|
||||
@@ -99,9 +100,9 @@ func (r *Runner) listAvailableStoreTags(store *loader.Store) {
|
||||
for _, tag := range tagsList {
|
||||
if r.options.JSONL {
|
||||
marshalled, _ := jsoniter.Marshal(tag)
|
||||
r.Logger.Debug().Msgf("%s", string(marshalled))
|
||||
gologger.Silent().Msgf("%s\n", string(marshalled))
|
||||
} else {
|
||||
r.Logger.Debug().Msgf("%s (%d)", tag.Key, tag.Value)
|
||||
gologger.Silent().Msgf("%s (%d)\n", tag.Key, tag.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +58,6 @@ type NucleiExecutorOptions struct {
|
||||
Colorizer aurora.Aurora
|
||||
Parser parser.Parser
|
||||
TemporaryDirectory string
|
||||
Logger *gologger.Logger
|
||||
}
|
||||
|
||||
func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) {
|
||||
@@ -67,7 +66,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,
|
||||
@@ -86,7 +85,6 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) {
|
||||
FuzzParamsFrequency: fuzzFreqCache,
|
||||
GlobalMatchers: globalmatchers.New(),
|
||||
FuzzStatsDB: opts.FuzzStatsDB,
|
||||
Logger: opts.Logger,
|
||||
}
|
||||
|
||||
if opts.Options.ShouldUseHostError() {
|
||||
@@ -95,7 +93,7 @@ func newNucleiExecutor(opts *NucleiExecutorOptions) (*nucleiExecutor, error) {
|
||||
maxHostError = 100 // auto adjust for fuzzings
|
||||
}
|
||||
if opts.Options.TemplateThreads > maxHostError {
|
||||
opts.Logger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads)
|
||||
gologger.Info().Msgf("Adjusting max-host-error to the concurrency value: %d", opts.Options.TemplateThreads)
|
||||
|
||||
maxHostError = opts.Options.TemplateThreads
|
||||
}
|
||||
@@ -109,7 +107,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.")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
|
||||
+3
-34
@@ -19,7 +19,6 @@ 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
|
||||
@@ -206,7 +205,7 @@ func EnableHeadlessWithOpts(hopts *HeadlessOpts) NucleiSDKOptions {
|
||||
e.opts.UseInstalledChrome = hopts.UseChrome
|
||||
}
|
||||
if engine.MustDisableSandbox() {
|
||||
e.Logger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox")
|
||||
gologger.Warning().Msgf("The current platform and privileged user will run the browser without sandbox\n")
|
||||
}
|
||||
browser, err := engine.New(e.opts)
|
||||
if err != nil {
|
||||
@@ -297,8 +296,8 @@ func WithNetworkConfig(opts NetworkConfig) NucleiSDKOptions {
|
||||
if e.opts.ShouldUseHostError() {
|
||||
maxHostError := opts.MaxHostError
|
||||
if e.opts.TemplateThreads > maxHostError {
|
||||
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)
|
||||
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)
|
||||
maxHostError = e.opts.TemplateThreads
|
||||
e.opts.MaxHostError = maxHostError
|
||||
}
|
||||
@@ -420,14 +419,6 @@ 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 {
|
||||
@@ -536,25 +527,3 @@ func WithResumeFile(file string) NucleiSDKOptions {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogger allows setting a shared 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
|
||||
}
|
||||
}
|
||||
+7
-10
@@ -14,7 +14,6 @@ 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
|
||||
@@ -22,14 +21,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,
|
||||
@@ -89,11 +88,9 @@ 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: defaultOptions,
|
||||
opts: types.DefaultOptions(),
|
||||
mode: threadSafe,
|
||||
}
|
||||
for _, option := range opts {
|
||||
@@ -128,8 +125,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.Copy()
|
||||
tmpEngine := &NucleiEngine{opts: baseOpts, mode: threadSafe}
|
||||
baseOpts := *e.eng.opts
|
||||
tmpEngine := &NucleiEngine{opts: &baseOpts, mode: threadSafe}
|
||||
for _, option := range opts {
|
||||
if err := option(tmpEngine); err != nil {
|
||||
return err
|
||||
@@ -145,7 +142,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)
|
||||
}
|
||||
@@ -157,7 +154,7 @@ func (e *ThreadSafeNucleiEngine) ExecuteNucleiWithOptsCtx(ctx context.Context, t
|
||||
}
|
||||
store.Load()
|
||||
|
||||
inputProvider := provider.NewSimpleInputProviderWithUrls(e.eng.opts.ExecutionId, targets...)
|
||||
inputProvider := provider.NewSimpleInputProviderWithUrls(targets...)
|
||||
|
||||
if len(store.Templates()) == 0 && len(store.Workflows()) == 0 {
|
||||
return ErrNoTemplatesAvailable
|
||||
|
||||
+15
-57
@@ -5,9 +5,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"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"
|
||||
@@ -29,7 +27,6 @@ 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
|
||||
@@ -67,7 +64,6 @@ type NucleiEngine struct {
|
||||
templatesLoaded bool
|
||||
|
||||
// unexported core fields
|
||||
ctx context.Context
|
||||
interactshClient *interactsh.Client
|
||||
catalog catalog.Catalog
|
||||
rateLimiter *ratelimit.Limiter
|
||||
@@ -88,15 +84,12 @@ type NucleiEngine struct {
|
||||
customWriter output.Writer
|
||||
customProgress progress.Progress
|
||||
rc reporting.Client
|
||||
executerOpts *protocols.ExecutorOptions
|
||||
|
||||
// Logger instance for the engine
|
||||
Logger *gologger.Logger
|
||||
executerOpts protocols.ExecutorOptions
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
@@ -131,9 +124,9 @@ func (e *NucleiEngine) GetWorkflows() []*templates.Template {
|
||||
func (e *NucleiEngine) LoadTargets(targets []string, probeNonHttp bool) {
|
||||
for _, target := range targets {
|
||||
if probeNonHttp {
|
||||
_ = e.inputProvider.SetWithProbe(e.opts.ExecutionId, target, e.httpxClient)
|
||||
_ = e.inputProvider.SetWithProbe(target, e.httpxClient)
|
||||
} else {
|
||||
e.inputProvider.Set(e.opts.ExecutionId, target)
|
||||
e.inputProvider.Set(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,9 +136,9 @@ func (e *NucleiEngine) LoadTargetsFromReader(reader io.Reader, probeNonHttp bool
|
||||
buff := bufio.NewScanner(reader)
|
||||
for buff.Scan() {
|
||||
if probeNonHttp {
|
||||
_ = e.inputProvider.SetWithProbe(e.opts.ExecutionId, buff.Text(), e.httpxClient)
|
||||
_ = e.inputProvider.SetWithProbe(buff.Text(), e.httpxClient)
|
||||
} else {
|
||||
e.inputProvider.Set(e.opts.ExecutionId, buff.Text())
|
||||
e.inputProvider.Set(buff.Text())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,7 +161,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
|
||||
@@ -236,7 +229,7 @@ func (e *NucleiEngine) closeInternal() {
|
||||
// Close all resources used by nuclei engine
|
||||
func (e *NucleiEngine) Close() {
|
||||
e.closeInternal()
|
||||
protocolinit.Close(e.opts.ExecutionId)
|
||||
protocolinit.Close()
|
||||
}
|
||||
|
||||
// ExecuteCallbackWithCtx executes templates on targets and calls callback on each result(only if results are found)
|
||||
@@ -253,9 +246,9 @@ func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...f
|
||||
}
|
||||
|
||||
filtered := []func(event *output.ResultEvent){}
|
||||
for _, cb := range callback {
|
||||
if cb != nil {
|
||||
filtered = append(filtered, cb)
|
||||
for _, callback := range callback {
|
||||
if callback != nil {
|
||||
filtered = append(filtered, callback)
|
||||
}
|
||||
}
|
||||
e.resultCallbacks = append(e.resultCallbacks, filtered...)
|
||||
@@ -265,32 +258,15 @@ func (e *NucleiEngine) ExecuteCallbackWithCtx(ctx context.Context, callback ...f
|
||||
return ErrNoTemplatesAvailable
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
_ = e.engine.ExecuteScanWithOpts(ctx, templatesAndWorkflows, e.inputProvider, false)
|
||||
defer e.engine.WorkPool().Wait()
|
||||
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 {
|
||||
ctx := context.Background()
|
||||
if e.ctx != nil {
|
||||
ctx = e.ctx
|
||||
}
|
||||
return e.ExecuteCallbackWithCtx(ctx, callback...)
|
||||
return e.ExecuteCallbackWithCtx(context.Background(), callback...)
|
||||
}
|
||||
|
||||
// Options return nuclei Type Options
|
||||
@@ -311,12 +287,9 @@ 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: defaultOptions,
|
||||
opts: types.DefaultOptions(),
|
||||
mode: singleInstance,
|
||||
ctx: ctx,
|
||||
}
|
||||
for _, option := range options {
|
||||
if err := option(e); err != nil {
|
||||
@@ -333,18 +306,3 @@ func NewNucleiEngineCtx(ctx context.Context, options ...NucleiSDKOptions) (*Nucl
|
||||
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{})
|
||||
go func() {
|
||||
defer close(ch)
|
||||
wg.Wait()
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
+14
-44
@@ -8,7 +8,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/input"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/reporting"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/pkg/errors"
|
||||
@@ -30,6 +29,7 @@ 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,6 +37,8 @@ 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)
|
||||
@@ -96,39 +98,27 @@ 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 {
|
||||
e.Logger.SetMaxLevel(levels.LevelVerbose)
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
|
||||
} else if e.opts.Debug {
|
||||
e.Logger.SetMaxLevel(levels.LevelDebug)
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug)
|
||||
} else if e.opts.Silent {
|
||||
e.Logger.SetMaxLevel(levels.LevelSilent)
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
|
||||
}
|
||||
|
||||
if err := runner.ValidateOptions(e.opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.opts.Parser != nil {
|
||||
if op, ok := e.opts.Parser.(*templates.Parser); ok {
|
||||
e.parser = op
|
||||
}
|
||||
e.parser = templates.NewParser()
|
||||
|
||||
if sharedInit == nil || protocolstate.ShouldInit() {
|
||||
sharedInit = &sync.Once{}
|
||||
}
|
||||
|
||||
if e.parser == nil {
|
||||
e.parser = templates.NewParser()
|
||||
}
|
||||
|
||||
if protocolstate.ShouldInit(e.opts.ExecutionId) {
|
||||
sharedInit.Do(func() {
|
||||
_ = protocolinit.Init(e.opts)
|
||||
}
|
||||
})
|
||||
|
||||
if e.opts.ProxyInternal && e.opts.AliveHttpProxy != "" || e.opts.AliveSocksProxy != "" {
|
||||
httpclient, err := httpclientpool.Get(e.opts, &httpclientpool.Configuration{})
|
||||
@@ -170,7 +160,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,
|
||||
@@ -183,13 +173,12 @@ 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")
|
||||
}
|
||||
@@ -231,25 +220,6 @@ 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)
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
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()
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/projectdiscovery/goflags"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
|
||||
"github.com/projectdiscovery/utils/env"
|
||||
@@ -41,18 +42,15 @@ 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"`
|
||||
Logger *gologger.Logger `json:"-"` // logger
|
||||
LatestNucleiVersion string `json:"nuclei-latest-version"`
|
||||
LatestNucleiTemplatesVersion string `json:"nuclei-templates-latest-version"`
|
||||
LatestNucleiIgnoreHash string `json:"nuclei-latest-ignore-hash,omitempty"`
|
||||
|
||||
// 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.
|
||||
@@ -107,29 +105,21 @@ 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
|
||||
}
|
||||
|
||||
@@ -221,7 +211,7 @@ func (c *Config) GetCacheDir() string {
|
||||
func (c *Config) SetConfigDir(dir string) {
|
||||
c.configDir = dir
|
||||
if err := c.createConfigDirIfNotExists(); err != nil {
|
||||
c.Logger.Fatal().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err)
|
||||
gologger.Fatal().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err)
|
||||
}
|
||||
|
||||
// if folder already exists read config or create new
|
||||
@@ -229,7 +219,7 @@ func (c *Config) SetConfigDir(dir string) {
|
||||
// create new config
|
||||
applyDefaultConfig()
|
||||
if err2 := c.WriteTemplatesConfig(); err2 != nil {
|
||||
c.Logger.Fatal().Msgf("Could not create nuclei config file at %s: %s", c.getTemplatesConfigFilePath(), err2)
|
||||
gologger.Fatal().Msgf("Could not create nuclei config file at %s: %s", c.getTemplatesConfigFilePath(), err2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,14 +319,14 @@ func (c *Config) createConfigDirIfNotExists() error {
|
||||
// to the current config directory
|
||||
func (c *Config) copyIgnoreFile() {
|
||||
if err := c.createConfigDirIfNotExists(); err != nil {
|
||||
c.Logger.Error().Msgf("Could not create nuclei config directory at %s: %s", c.configDir, err)
|
||||
gologger.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 {
|
||||
c.Logger.Error().Msgf("Could not copy nuclei ignore file at %s: %s", ignoreFilePath, err)
|
||||
gologger.Error().Msgf("Could not copy nuclei ignore file at %s: %s", ignoreFilePath, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,6 +367,9 @@ 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 != "" {
|
||||
@@ -392,7 +385,6 @@ func init() {
|
||||
DefaultConfig = &Config{
|
||||
homeDir: folderutil.HomeDirOrDefault(""),
|
||||
configDir: ConfigDir,
|
||||
Logger: gologger.DefaultLogger,
|
||||
}
|
||||
|
||||
// when enabled will log events in more verbosity than -v or -debug
|
||||
@@ -414,7 +406,9 @@ 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
|
||||
@@ -429,3 +423,61 @@ 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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ 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"
|
||||
@@ -97,7 +98,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) {
|
||||
return index, nil
|
||||
}
|
||||
}
|
||||
DefaultConfig.Logger.Error().Msgf("failed to read index file creating new one: %v", err)
|
||||
gologger.Error().Msgf("failed to read index file creating new one: %v", err)
|
||||
}
|
||||
|
||||
ignoreDirs := DefaultConfig.GetAllCustomTemplateDirs()
|
||||
@@ -108,7 +109,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) {
|
||||
}
|
||||
err := filepath.WalkDir(DefaultConfig.TemplatesDirectory, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
DefaultConfig.Logger.Verbose().Msgf("failed to walk path=%v err=%v", path, err)
|
||||
gologger.Verbose().Msgf("failed to walk path=%v err=%v", path, err)
|
||||
return nil
|
||||
}
|
||||
if d.IsDir() || !IsTemplate(path) || stringsutil.ContainsAny(path, ignoreDirs...) {
|
||||
@@ -117,7 +118,7 @@ func GetNucleiTemplatesIndex() (map[string]string, error) {
|
||||
// get template id from file
|
||||
id, err := getTemplateID(path)
|
||||
if err != nil || id == "" {
|
||||
DefaultConfig.Logger.Verbose().Msgf("failed to get template id from file=%v got id=%v err=%v", path, id, err)
|
||||
gologger.Verbose().Msgf("failed to get template id from file=%v got id=%v err=%v", path, id, err)
|
||||
return nil
|
||||
}
|
||||
index[id] = path
|
||||
|
||||
@@ -8,6 +8,7 @@ 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"
|
||||
@@ -83,7 +84,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 {
|
||||
config.DefaultConfig.Logger.Print().Msgf("[%v] requested Template path %s is deprecated, please update to %s\n", aurora.Yellow("WRN").String(), target, absPath)
|
||||
gologger.DefaultLogger.Print().Msgf("[%v] requested Template path %s is deprecated, please update to %s\n", aurora.Yellow("WRN").String(), target, absPath)
|
||||
}
|
||||
deprecatedPathsCounter++
|
||||
}
|
||||
@@ -301,6 +302,6 @@ func PrintDeprecatedPathsMsgIfApplicable(isSilent bool) {
|
||||
return
|
||||
}
|
||||
if deprecatedPathsCounter > 0 && !isSilent {
|
||||
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)
|
||||
gologger.Print().Msgf("[%v] Found %v template[s] loaded with deprecated paths, update before v3 for continued support.\n", aurora.Yellow("WRN").String(), deprecatedPathsCounter)
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ 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"
|
||||
@@ -56,8 +57,8 @@ func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, e
|
||||
return nil, errorutil.New("Failed to generate template: %v", err)
|
||||
}
|
||||
|
||||
options.Logger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID)
|
||||
options.Logger.Info().Msgf("Generated template path: %s", templateFile)
|
||||
gologger.Info().Msgf("Generated template available at: https://cloud.projectdiscovery.io/templates/%s", templateID)
|
||||
gologger.Info().Msgf("Generated template path: %s", templateFile)
|
||||
|
||||
// Check if we should display the template
|
||||
// This happens when:
|
||||
@@ -75,7 +76,7 @@ func getAIGeneratedTemplates(prompt string, options *types.Options) ([]string, e
|
||||
template = buf.String()
|
||||
}
|
||||
}
|
||||
options.Logger.Debug().Msgf("\n%s", template)
|
||||
gologger.Silent().Msgf("\n%s", template)
|
||||
// FIXME:
|
||||
// we should not be exiting the program here
|
||||
// but we need to find a better way to handle this
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/pkg/errors"
|
||||
@@ -17,7 +18,6 @@ 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,9 +27,7 @@ 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 (
|
||||
@@ -67,8 +65,7 @@ type Config struct {
|
||||
IncludeConditions []string
|
||||
|
||||
Catalog catalog.Catalog
|
||||
ExecutorOptions *protocols.ExecutorOptions
|
||||
Logger *gologger.Logger
|
||||
ExecutorOptions protocols.ExecutorOptions
|
||||
}
|
||||
|
||||
// Store is a storage for loaded nuclei templates
|
||||
@@ -85,15 +82,13 @@ 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,
|
||||
@@ -116,7 +111,6 @@ func NewConfig(options *types.Options, catalog catalog.Catalog, executerOpts *pr
|
||||
Catalog: catalog,
|
||||
ExecutorOptions: executerOpts,
|
||||
AITemplatePrompt: options.AITemplatePrompt,
|
||||
Logger: options.Logger,
|
||||
}
|
||||
loaderConfig.RemoteTemplateDomainList = append(loaderConfig.RemoteTemplateDomainList, TrustedTemplateDomains...)
|
||||
return &loaderConfig
|
||||
@@ -151,7 +145,6 @@ 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
|
||||
@@ -245,8 +238,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)
|
||||
@@ -302,11 +295,11 @@ func (store *Store) LoadTemplatesOnlyMetadata() error {
|
||||
if strings.Contains(err.Error(), templates.ErrExcluded.Error()) {
|
||||
stats.Increment(templates.TemplatesExcludedStats)
|
||||
if config.DefaultConfig.LogAllEvents {
|
||||
store.logger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error())
|
||||
gologger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
store.logger.Warning().Msg(err.Error())
|
||||
gologger.Warning().Msg(err.Error())
|
||||
}
|
||||
}
|
||||
parserItem, ok := store.config.ExecutorOptions.Parser.(*templates.Parser)
|
||||
@@ -365,13 +358,15 @@ 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 store.config.ExecutorOptions.Parser.LoadWorkflow(templatePath, store.config.Catalog)
|
||||
return false, nil
|
||||
// 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 store.config.ExecutorOptions.Parser.LoadTemplate(templatePath, store.tagFilter, nil, store.config.Catalog)
|
||||
return false, nil
|
||||
// return store.config.ExecutorOptions.Parser.LoadTemplate(templatePath, store.tagFilter, nil, store.config.Catalog)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -380,7 +375,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
|
||||
|
||||
for templatePath := range filteredTemplatePaths {
|
||||
if _, err := load(templatePath, store.tagFilter); err != nil {
|
||||
if isParsingError(store, "Error occurred loading template %s: %s\n", templatePath, err) {
|
||||
if isParsingError("Error occurred loading template %s: %s\n", templatePath, err) {
|
||||
areTemplatesValid = false
|
||||
continue
|
||||
}
|
||||
@@ -388,7 +383,7 @@ func (store *Store) areWorkflowOrTemplatesValid(filteredTemplatePaths map[string
|
||||
|
||||
template, err := templates.Parse(templatePath, store.preprocessor, store.config.ExecutorOptions)
|
||||
if err != nil {
|
||||
if isParsingError(store, "Error occurred parsing template %s: %s\n", templatePath, err) {
|
||||
if isParsingError("Error occurred parsing template %s: %s\n", templatePath, err) {
|
||||
areTemplatesValid = false
|
||||
continue
|
||||
}
|
||||
@@ -413,7 +408,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
|
||||
store.logger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID)
|
||||
gologger.Warning().Msgf("Found duplicate template ID during validation '%s' => '%s': %s\n", templatePath, existingTemplatePath, template.ID)
|
||||
}
|
||||
if !isWorkflow && len(template.Workflows) > 0 {
|
||||
continue
|
||||
@@ -436,7 +431,7 @@ func areWorkflowTemplatesValid(store *Store, workflows []*workflows.WorkflowTemp
|
||||
}
|
||||
_, err := store.config.Catalog.GetTemplatePath(workflow.Template)
|
||||
if err != nil {
|
||||
if isParsingError(store, "Error occurred loading template %s: %s\n", workflow.Template, err) {
|
||||
if isParsingError("Error occurred loading template %s: %s\n", workflow.Template, err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -444,14 +439,14 @@ func areWorkflowTemplatesValid(store *Store, workflows []*workflows.WorkflowTemp
|
||||
return true
|
||||
}
|
||||
|
||||
func isParsingError(store *Store, message string, template string, err error) bool {
|
||||
func isParsingError(message string, template string, err error) bool {
|
||||
if errors.Is(err, templates.ErrExcluded) {
|
||||
return false
|
||||
}
|
||||
if errors.Is(err, templates.ErrCreateTemplateExecutor) {
|
||||
return false
|
||||
}
|
||||
store.logger.Error().Msgf(message, template, err)
|
||||
gologger.Error().Msgf(message, template, err)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -470,12 +465,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 {
|
||||
store.logger.Warning().Msgf("Could not load workflow %s: %s\n", workflowPath, err)
|
||||
gologger.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 {
|
||||
store.logger.Warning().Msgf("Could not parse workflow %s: %s\n", workflowPath, err)
|
||||
gologger.Warning().Msgf("Could not parse workflow %s: %s\n", workflowPath, err)
|
||||
} else if parsed != nil {
|
||||
loadedWorkflows = append(loadedWorkflows, parsed)
|
||||
}
|
||||
@@ -507,22 +502,10 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
var wgLoadTemplates sync.WaitGroup
|
||||
|
||||
for templatePath := range templatePathMap {
|
||||
wgLoadTemplates.Add()
|
||||
wgLoadTemplates.Add(1)
|
||||
go func(templatePath string) {
|
||||
defer wgLoadTemplates.Done()
|
||||
|
||||
@@ -534,7 +517,7 @@ func (store *Store) LoadTemplatesWithTags(templatesList, tags []string) []*templ
|
||||
if !errors.Is(err, templates.ErrIncompatibleWithOfflineMatching) {
|
||||
stats.Increment(templates.RuntimeWarningsStats)
|
||||
}
|
||||
store.logger.Warning().Msgf("Could not parse template %s: %s\n", templatePath, err)
|
||||
gologger.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
|
||||
@@ -569,13 +552,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 {
|
||||
store.logger.Print().Msgf("[%v] Headless flag is required for headless template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
gologger.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 {
|
||||
store.logger.Print().Msgf("[%v] Code flag is required for code protocol template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
gologger.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
|
||||
@@ -583,12 +566,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 {
|
||||
store.logger.Print().Msgf("[%v] Tampered/Unsigned template at %v.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
gologger.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 {
|
||||
store.logger.Print().Msgf("[%v] -dast flag is required for DAST template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
gologger.Print().Msgf("[%v] -dast flag is required for DAST template '%s'.\n", aurora.Yellow("WRN").String(), templatePath)
|
||||
}
|
||||
} else {
|
||||
loadTemplate(parsed)
|
||||
@@ -599,11 +582,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 {
|
||||
store.logger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error())
|
||||
gologger.Print().Msgf("[%v] %v\n", aurora.Yellow("WRN").String(), err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
store.logger.Warning().Msg(err.Error())
|
||||
gologger.Warning().Msg(err.Error())
|
||||
}
|
||||
}(templatePath)
|
||||
}
|
||||
@@ -659,7 +642,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) {
|
||||
s.logger.Error().Msgf("Could not find template '%s': %s", template, err)
|
||||
gologger.Error().Msgf("Could not find template '%s': %s", template, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,13 @@ 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
|
||||
@@ -31,73 +28,67 @@ type RemoteContent struct {
|
||||
}
|
||||
|
||||
func getRemoteTemplatesAndWorkflows(templateURLs, workflowURLs, remoteTemplateDomainList []string) ([]string, []string, error) {
|
||||
var (
|
||||
err error
|
||||
muErr sync.Mutex
|
||||
)
|
||||
remoteTemplateList := sliceutil.NewSyncSlice[string]()
|
||||
remoteWorkFlowList := sliceutil.NewSyncSlice[string]()
|
||||
remoteContentChannel := make(chan RemoteContent)
|
||||
|
||||
awg, errAwg := syncutil.New(syncutil.WithSize(50))
|
||||
if errAwg != nil {
|
||||
return nil, nil, errAwg
|
||||
for _, templateURL := range templateURLs {
|
||||
go getRemoteContent(templateURL, remoteTemplateDomainList, remoteContentChannel, Template)
|
||||
}
|
||||
for _, workflowURL := range workflowURLs {
|
||||
go getRemoteContent(workflowURL, remoteTemplateDomainList, remoteContentChannel, Workflow)
|
||||
}
|
||||
|
||||
loadItem := func(URL string, contentType ContentType) {
|
||||
defer awg.Done()
|
||||
|
||||
remoteContent := getRemoteContent(URL, remoteTemplateDomainList, contentType)
|
||||
var remoteTemplateList []string
|
||||
var remoteWorkFlowList []string
|
||||
var err error
|
||||
for i := 0; i < (len(templateURLs) + len(workflowURLs)); i++ {
|
||||
remoteContent := <-remoteContentChannel
|
||||
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(remoteContent.Content...)
|
||||
remoteTemplateList = append(remoteTemplateList, remoteContent.Content...)
|
||||
case Workflow:
|
||||
remoteWorkFlowList.Append(remoteContent.Content...)
|
||||
remoteWorkFlowList = append(remoteWorkFlowList, remoteContent.Content...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
return remoteTemplateList, remoteWorkFlowList, err
|
||||
}
|
||||
|
||||
func getRemoteContent(URL string, remoteTemplateDomainList []string, contentType ContentType) RemoteContent {
|
||||
func getRemoteContent(URL string, remoteTemplateDomainList []string, remoteContentChannel chan<- RemoteContent, contentType ContentType) {
|
||||
if err := validateRemoteTemplateURL(URL, remoteTemplateDomainList); err != nil {
|
||||
return RemoteContent{Error: err}
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Error: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(URL, "http") && stringsutil.HasSuffixAny(URL, extensions.YAML) {
|
||||
return RemoteContent{
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Content: []string{URL},
|
||||
Type: contentType,
|
||||
}
|
||||
return
|
||||
}
|
||||
response, err := retryablehttp.DefaultClient().Get(URL)
|
||||
if err != nil {
|
||||
return RemoteContent{Error: err}
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Error: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
_ = response.Body.Close()
|
||||
}()
|
||||
_ = response.Body.Close()
|
||||
}()
|
||||
if response.StatusCode < 200 || response.StatusCode > 299 {
|
||||
return RemoteContent{Error: fmt.Errorf("get \"%s\": unexpect status %d", URL, response.StatusCode)}
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Error: fmt.Errorf("get \"%s\": unexpect status %d", URL, response.StatusCode),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(response.Body)
|
||||
@@ -109,17 +100,23 @@ func getRemoteContent(URL string, remoteTemplateDomainList []string, contentType
|
||||
}
|
||||
if utils.IsURL(text) {
|
||||
if err := validateRemoteTemplateURL(text, remoteTemplateDomainList); err != nil {
|
||||
return RemoteContent{Error: err}
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Error: err,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
templateList = append(templateList, text)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return RemoteContent{Error: errors.Wrap(err, "get \"%s\"")}
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Error: errors.Wrap(err, "get \"%s\""),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
return RemoteContent{
|
||||
remoteContentChannel <- RemoteContent{
|
||||
Content: templateList,
|
||||
Type: contentType,
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,7 +1,6 @@
|
||||
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"
|
||||
@@ -18,16 +17,14 @@ 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
|
||||
@@ -50,12 +47,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
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@ package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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"
|
||||
@@ -49,7 +51,7 @@ func (e *Engine) ExecuteScanWithOpts(ctx context.Context, templatesList []*templ
|
||||
totalReqAfterClustering := getRequestCount(finalTemplates) * int(target.Count())
|
||||
|
||||
if !noCluster && totalReqAfterClustering < totalReqBeforeCluster {
|
||||
e.Logger.Info().Msgf("Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering)
|
||||
gologger.Info().Msgf("Templates clustered: %d (Reduced %d Requests)", clusterCount, totalReqBeforeCluster-totalReqAfterClustering)
|
||||
}
|
||||
|
||||
// 0 matches means no templates were found in the directory
|
||||
@@ -131,6 +133,7 @@ func (e *Engine) executeTemplateSpray(ctx context.Context, templatesList []*temp
|
||||
wg.Add()
|
||||
go func(tpl *templates.Template) {
|
||||
defer wg.Done()
|
||||
fmt.Printf("[spray] executing template: %s\n", tpl.ID)
|
||||
// All other request types are executed here
|
||||
// Note: executeTemplateWithTargets creates goroutines and blocks
|
||||
// given template is executed on all targets
|
||||
|
||||
+15
-24
@@ -2,12 +2,12 @@ package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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"
|
||||
@@ -39,7 +39,7 @@ func (e *Engine) executeAllSelfContained(ctx context.Context, alltemplates []*te
|
||||
match, err = template.Executer.Execute(ctx)
|
||||
}
|
||||
if err != nil {
|
||||
e.options.Logger.Warning().Msgf("[%s] Could not execute step (self-contained): %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)
|
||||
@@ -79,8 +79,10 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
}
|
||||
|
||||
target.Iterate(func(scannedValue *contextargs.MetaInput) bool {
|
||||
fmt.Printf("[iter] iterating target: %s %s\n", template.ID, scannedValue.Input)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
fmt.Printf("[iter] ctx done: %s %s\n", template.ID, scannedValue.Input)
|
||||
return false // exit
|
||||
default:
|
||||
}
|
||||
@@ -89,13 +91,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
|
||||
e.options.Logger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Template already completed", template.ID, scannedValue.Input)
|
||||
gologger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Template already completed\n", template.ID, scannedValue.Input)
|
||||
skip = true
|
||||
} else if index < resumeFromInfo.SkipUnder { // index lower than the sliding window (bulk-size)
|
||||
e.options.Logger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Target already processed", template.ID, scannedValue.Input)
|
||||
gologger.Debug().Msgf("[%s] Skipping \"%s\": Resume - Target already processed\n", template.ID, scannedValue.Input)
|
||||
skip = true
|
||||
} else if _, isInFlight := resumeFromInfo.InFlight[index]; isInFlight { // the target wasn't completed successfully
|
||||
e.options.Logger.Debug().Msgf("[%s] Repeating \"%s\": Resume - Target wasn't completed", template.ID, scannedValue.Input)
|
||||
gologger.Debug().Msgf("[%s] Repeating \"%s\": Resume - Target wasn't completed\n", 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)
|
||||
@@ -109,22 +111,7 @@ 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)
|
||||
}
|
||||
fmt.Printf("[iter] host error: %s %s\n", template.ID, scannedValue.Input)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -133,6 +120,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
defer wg.Done()
|
||||
defer cleanupInFlight(index)
|
||||
if skip {
|
||||
fmt.Printf("[iter] skip: %s %s\n", template.ID, value.Input)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -145,6 +133,7 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
case types.WorkflowProtocol:
|
||||
match = e.executeWorkflow(ctx, template.CompiledWorkflow)
|
||||
default:
|
||||
fmt.Printf("[iter] executing template: %s %s\n", template.ID, value.Input)
|
||||
if e.Callback != nil {
|
||||
if results, err := template.Executer.ExecuteWithResults(ctx); err == nil {
|
||||
for _, result := range results {
|
||||
@@ -156,8 +145,10 @@ func (e *Engine) executeTemplateWithTargets(ctx context.Context, template *templ
|
||||
match, err = template.Executer.Execute(ctx)
|
||||
}
|
||||
}
|
||||
fmt.Printf("[iter] match: %s %s %v\n", template.ID, value.Input, match)
|
||||
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)
|
||||
fmt.Printf("[iter] error: %s %s\n", template.ID, value.Input)
|
||||
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)
|
||||
@@ -223,7 +214,7 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t
|
||||
}
|
||||
}
|
||||
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)
|
||||
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)
|
||||
|
||||
+6
-15
@@ -1,25 +1,23 @@
|
||||
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"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/utils"
|
||||
osutils "github.com/projectdiscovery/utils/os"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDownloadCustomTemplatesFromGitHub(t *testing.T) {
|
||||
// Capture output to check for rate limit errors
|
||||
outputBuffer := &bytes.Buffer{}
|
||||
gologger.DefaultLogger.SetWriter(&utils.CaptureWriter{Buffer: outputBuffer})
|
||||
gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug)
|
||||
if osutils.IsOSX() {
|
||||
t.Skip("skipping on macos due to unknown failure (works locally)")
|
||||
}
|
||||
|
||||
gologger.DefaultLogger.SetWriter(&testutils.NoopWriter{})
|
||||
|
||||
templatesDirectory := t.TempDir()
|
||||
config.DefaultConfig.SetTemplatesDir(templatesDirectory)
|
||||
@@ -31,12 +29,5 @@ 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")
|
||||
}
|
||||
@@ -61,6 +61,7 @@ func checkTimingDependency(
|
||||
|
||||
var requestsSent []requestsSentMetadata
|
||||
for requestsLeft > 0 {
|
||||
|
||||
isCorrelationPossible, delayRecieved, err := sendRequestAndTestConfidence(regression, highSleepTimeSeconds, requestSender, baselineDelay)
|
||||
if err != nil {
|
||||
return false, "", err
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,7 +2,6 @@ package openapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
@@ -163,7 +162,9 @@ func openAPIExample(schema *openapi3.Schema, cache map[*openapi3.Schema]*cachedS
|
||||
return nil, ErrNoExample
|
||||
}
|
||||
|
||||
maps.Copy(example, value)
|
||||
for k, v := range value {
|
||||
example[k] = v
|
||||
}
|
||||
}
|
||||
return example, nil
|
||||
}
|
||||
|
||||
@@ -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(_ string, value string) {}
|
||||
func (i *HttpInputProvider) Set(value string) {}
|
||||
|
||||
// SetWithProbe adds item to input provider with http probing
|
||||
// No-op for this provider
|
||||
func (i *HttpInputProvider) SetWithProbe(_ string, value string, probe types.InputLivenessProbe) error {
|
||||
func (i *HttpInputProvider) SetWithProbe(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(_ string, value string) error {
|
||||
func (i *HttpInputProvider) SetWithExclusions(value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -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(executionId string, value string)
|
||||
Set(value string)
|
||||
// SetWithProbe adds item to input provider with http probing
|
||||
SetWithProbe(executionId string, value string, probe types.InputLivenessProbe) error
|
||||
SetWithProbe(value string, probe types.InputLivenessProbe) error
|
||||
// SetWithExclusions adds item to input provider if it doesn't match any of the exclusions
|
||||
SetWithExclusions(executionId string, value string) error
|
||||
SetWithExclusions(value string) error
|
||||
// InputType returns the type of input provider
|
||||
InputType() string
|
||||
// Close the input provider and cleanup any resources
|
||||
|
||||
@@ -139,7 +139,7 @@ func (i *ListInputProvider) Iterate(callback func(value *contextargs.MetaInput)
|
||||
}
|
||||
|
||||
// Set normalizes and stores passed input values
|
||||
func (i *ListInputProvider) Set(executionId string, value string) {
|
||||
func (i *ListInputProvider) Set(value string) {
|
||||
URL := strings.TrimSpace(value)
|
||||
if URL == "" {
|
||||
return
|
||||
@@ -169,12 +169,7 @@ func (i *ListInputProvider) Set(executionId string, value string) {
|
||||
|
||||
if i.ipOptions.ScanAllIPs {
|
||||
// scan all ips
|
||||
dialers := protocolstate.GetDialersWithId(executionId)
|
||||
if dialers == nil {
|
||||
panic("dialers with executionId " + executionId + " not found")
|
||||
}
|
||||
|
||||
dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname())
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname())
|
||||
if err == nil {
|
||||
if (len(dnsData.A) + len(dnsData.AAAA)) > 0 {
|
||||
var ips []string
|
||||
@@ -206,12 +201,7 @@ func (i *ListInputProvider) Set(executionId string, value string) {
|
||||
ips := []string{}
|
||||
// only scan the target but ipv6 if it has one
|
||||
if i.ipOptions.IPV6 {
|
||||
dialers := protocolstate.GetDialersWithId(executionId)
|
||||
if dialers == nil {
|
||||
panic("dialers with executionId " + executionId + " not found")
|
||||
}
|
||||
|
||||
dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname())
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname())
|
||||
if err == nil && len(dnsData.AAAA) > 0 {
|
||||
// pick/ prefer 1st
|
||||
ips = append(ips, dnsData.AAAA[0])
|
||||
@@ -238,17 +228,17 @@ func (i *ListInputProvider) Set(executionId string, value string) {
|
||||
}
|
||||
|
||||
// SetWithProbe only sets the input if it is live
|
||||
func (i *ListInputProvider) SetWithProbe(executionId string, value string, probe providerTypes.InputLivenessProbe) error {
|
||||
func (i *ListInputProvider) SetWithProbe(value string, probe providerTypes.InputLivenessProbe) error {
|
||||
probedValue, err := probe.ProbeURL(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.Set(executionId, probedValue)
|
||||
i.Set(probedValue)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWithExclusions normalizes and stores passed input values if not excluded
|
||||
func (i *ListInputProvider) SetWithExclusions(executionId string, value string) error {
|
||||
func (i *ListInputProvider) SetWithExclusions(value string) error {
|
||||
URL := strings.TrimSpace(value)
|
||||
if URL == "" {
|
||||
return nil
|
||||
@@ -257,7 +247,7 @@ func (i *ListInputProvider) SetWithExclusions(executionId string, value string)
|
||||
i.skippedCount++
|
||||
return nil
|
||||
}
|
||||
i.Set(executionId, URL)
|
||||
i.Set(URL)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -283,20 +273,18 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error {
|
||||
switch {
|
||||
case iputil.IsCIDR(target):
|
||||
ips := expand.CIDR(target)
|
||||
i.addTargets(options.ExecutionId, ips)
|
||||
i.addTargets(ips)
|
||||
case asn.IsASN(target):
|
||||
ips := expand.ASN(target)
|
||||
i.addTargets(options.ExecutionId, ips)
|
||||
i.addTargets(ips)
|
||||
default:
|
||||
i.Set(options.ExecutionId, target)
|
||||
i.Set(target)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle stdin
|
||||
if options.Stdin {
|
||||
i.scanInputFromReader(
|
||||
options.ExecutionId,
|
||||
readerutil.TimeoutReader{Reader: os.Stdin, Timeout: time.Duration(options.InputReadTimeout)})
|
||||
i.scanInputFromReader(readerutil.TimeoutReader{Reader: os.Stdin, Timeout: time.Duration(options.InputReadTimeout)})
|
||||
}
|
||||
|
||||
// Handle target file
|
||||
@@ -309,7 +297,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error {
|
||||
}
|
||||
}
|
||||
if input != nil {
|
||||
i.scanInputFromReader(options.ExecutionId, input)
|
||||
i.scanInputFromReader(input)
|
||||
_ = input.Close()
|
||||
}
|
||||
}
|
||||
@@ -329,7 +317,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error {
|
||||
return err
|
||||
}
|
||||
for c := range ch {
|
||||
i.Set(options.ExecutionId, c)
|
||||
i.Set(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +331,7 @@ func (i *ListInputProvider) initializeInputSources(opts *Options) error {
|
||||
ips := expand.ASN(target)
|
||||
i.removeTargets(ips)
|
||||
default:
|
||||
i.Del(options.ExecutionId, target)
|
||||
i.Del(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,19 +340,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(executionId string, reader io.Reader) {
|
||||
func (i *ListInputProvider) scanInputFromReader(reader io.Reader) {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
for scanner.Scan() {
|
||||
item := scanner.Text()
|
||||
switch {
|
||||
case iputil.IsCIDR(item):
|
||||
ips := expand.CIDR(item)
|
||||
i.addTargets(executionId, ips)
|
||||
i.addTargets(ips)
|
||||
case asn.IsASN(item):
|
||||
ips := expand.ASN(item)
|
||||
i.addTargets(executionId, ips)
|
||||
i.addTargets(ips)
|
||||
default:
|
||||
i.Set(executionId, item)
|
||||
i.Set(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,7 +371,7 @@ func (i *ListInputProvider) isExcluded(URL string) bool {
|
||||
return exists
|
||||
}
|
||||
|
||||
func (i *ListInputProvider) Del(executionId string, value string) {
|
||||
func (i *ListInputProvider) Del(value string) {
|
||||
URL := strings.TrimSpace(value)
|
||||
if URL == "" {
|
||||
return
|
||||
@@ -413,12 +401,7 @@ func (i *ListInputProvider) Del(executionId string, value string) {
|
||||
|
||||
if i.ipOptions.ScanAllIPs {
|
||||
// scan all ips
|
||||
dialers := protocolstate.GetDialersWithId(executionId)
|
||||
if dialers == nil {
|
||||
panic("dialers with executionId " + executionId + " not found")
|
||||
}
|
||||
|
||||
dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname())
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname())
|
||||
if err == nil {
|
||||
if (len(dnsData.A) + len(dnsData.AAAA)) > 0 {
|
||||
var ips []string
|
||||
@@ -450,12 +433,7 @@ func (i *ListInputProvider) Del(executionId string, value string) {
|
||||
ips := []string{}
|
||||
// only scan the target but ipv6 if it has one
|
||||
if i.ipOptions.IPV6 {
|
||||
dialers := protocolstate.GetDialersWithId(executionId)
|
||||
if dialers == nil {
|
||||
panic("dialers with executionId " + executionId + " not found")
|
||||
}
|
||||
|
||||
dnsData, err := dialers.Fastdialer.GetDNSData(urlx.Hostname())
|
||||
dnsData, err := protocolstate.Dialer.GetDNSData(urlx.Hostname())
|
||||
if err == nil && len(dnsData.AAAA) > 0 {
|
||||
// pick/ prefer 1st
|
||||
ips = append(ips, dnsData.AAAA[0])
|
||||
@@ -541,9 +519,9 @@ func (i *ListInputProvider) setHostMapStream(data string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ListInputProvider) addTargets(executionId string, targets []string) {
|
||||
func (i *ListInputProvider) addTargets(targets []string) {
|
||||
for _, target := range targets {
|
||||
i.Set(executionId, target)
|
||||
i.Set(target)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -19,10 +19,10 @@ func NewSimpleInputProvider() *SimpleInputProvider {
|
||||
}
|
||||
|
||||
// NewSimpleInputProviderWithUrls creates a new simple input provider with the given urls
|
||||
func NewSimpleInputProviderWithUrls(executionId string, urls ...string) *SimpleInputProvider {
|
||||
func NewSimpleInputProviderWithUrls(urls ...string) *SimpleInputProvider {
|
||||
provider := NewSimpleInputProvider()
|
||||
for _, url := range urls {
|
||||
provider.Set(executionId, url)
|
||||
provider.Set(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(_ string, value string) {
|
||||
func (s *SimpleInputProvider) Set(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(_ string, value string, probe types.InputLivenessProbe) error {
|
||||
func (s *SimpleInputProvider) SetWithProbe(value string, probe types.InputLivenessProbe) error {
|
||||
probedValue, err := probe.ProbeURL(value)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -61,7 +61,7 @@ func (s *SimpleInputProvider) SetWithProbe(_ string, value string, probe types.I
|
||||
}
|
||||
|
||||
// SetWithExclusions adds an item to the input provider if it doesn't match any of the exclusions
|
||||
func (s *SimpleInputProvider) SetWithExclusions(_ string, value string) error {
|
||||
func (s *SimpleInputProvider) SetWithExclusions(value string) error {
|
||||
metaInput := contextargs.NewMetaInput()
|
||||
metaInput.Input = value
|
||||
s.Inputs = append(s.Inputs, metaInput)
|
||||
|
||||
@@ -53,14 +53,11 @@ func (t *templateUpdateResults) String() string {
|
||||
},
|
||||
}
|
||||
table := tablewriter.NewWriter(&buff)
|
||||
table.Header([]string{"Total", "Added", "Modified", "Removed"})
|
||||
table.SetHeader([]string{"Total", "Added", "Modified", "Removed"})
|
||||
for _, v := range data {
|
||||
_ = table.Append(v)
|
||||
table.Append(v)
|
||||
}
|
||||
_ = table.Render()
|
||||
defer func() {
|
||||
_ = table.Close()
|
||||
}()
|
||||
table.Render()
|
||||
return buff.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/kitabisa/go-ci"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/generators"
|
||||
@@ -32,9 +32,6 @@ 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
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/types"
|
||||
)
|
||||
|
||||
@@ -11,13 +9,10 @@ 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
|
||||
|
||||
@@ -3,7 +3,7 @@ package compiler
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
syncutil "github.com/projectdiscovery/utils/sync"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/Mzack9999/goja_nodejs/console"
|
||||
"github.com/Mzack9999/goja_nodejs/require"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/dop251/goja_nodejs/console"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/kitabisa/go-ci"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
_ "github.com/projectdiscovery/nuclei/v3/pkg/js/generated/go/libbytes"
|
||||
@@ -84,7 +84,6 @@ 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.
|
||||
@@ -109,11 +108,8 @@ 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)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -5,7 +5,7 @@ package {{.PackageName}}
|
||||
import (
|
||||
{{$pkgName}} "{{.PackagePath}}"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package bytes
|
||||
import (
|
||||
lib_bytes "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/bytes"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package fs
|
||||
import (
|
||||
lib_fs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/fs"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package goconsole
|
||||
import (
|
||||
lib_goconsole "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/goconsole"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package ikev2
|
||||
import (
|
||||
lib_ikev2 "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ikev2"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package kerberos
|
||||
import (
|
||||
lib_kerberos "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/kerberos"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package ldap
|
||||
import (
|
||||
lib_ldap "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ldap"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package mssql
|
||||
import (
|
||||
lib_mssql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mssql"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package mysql
|
||||
import (
|
||||
lib_mysql "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/mysql"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net
|
||||
import (
|
||||
lib_net "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/net"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package oracle
|
||||
import (
|
||||
lib_oracle "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/oracle"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package pop3
|
||||
import (
|
||||
lib_pop3 "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/pop3"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package postgres
|
||||
import (
|
||||
lib_postgres "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/postgres"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package rdp
|
||||
import (
|
||||
lib_rdp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rdp"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package redis
|
||||
import (
|
||||
lib_redis "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/redis"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package rsync
|
||||
import (
|
||||
lib_rsync "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/rsync"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package smb
|
||||
import (
|
||||
lib_smb "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smb"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package smtp
|
||||
import (
|
||||
lib_smtp "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/smtp"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package ssh
|
||||
import (
|
||||
lib_ssh "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/ssh"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package structs
|
||||
import (
|
||||
lib_structs "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package telnet
|
||||
import (
|
||||
lib_telnet "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/telnet"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package vnc
|
||||
import (
|
||||
lib_vnc "github.com/projectdiscovery/nuclei/v3/pkg/js/libs/vnc"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package global
|
||||
import (
|
||||
"encoding/base64"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/logrusorgru/aurora"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/gojs"
|
||||
@@ -113,7 +113,8 @@ 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(ctx context.Context, host string, port string, timeout ...int) (bool, error) {
|
||||
FuncDecl: func(host string, port string, timeout ...int) (bool, error) {
|
||||
ctx := context.Background()
|
||||
if len(timeout) > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second)
|
||||
@@ -122,14 +123,7 @@ func initBuiltInFunc(runtime *goja.Runtime) {
|
||||
if host == "" || port == "" {
|
||||
return false, errkit.New("isPortOpen: host or port is empty")
|
||||
}
|
||||
|
||||
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))
|
||||
conn, err := protocolstate.Dialer.Dial(ctx, "tcp", net.JoinHostPort(host, port))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -144,7 +138,8 @@ 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(ctx context.Context, host string, port string, timeout ...int) (bool, error) {
|
||||
FuncDecl: func(host string, port string, timeout ...int) (bool, error) {
|
||||
ctx := context.Background()
|
||||
if len(timeout) > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout[0])*time.Second)
|
||||
@@ -153,14 +148,7 @@ func initBuiltInFunc(runtime *goja.Runtime) {
|
||||
if host == "" || port == "" {
|
||||
return false, errkit.New("isPortOpen: host or port is empty")
|
||||
}
|
||||
|
||||
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))
|
||||
conn, err := protocolstate.Dialer.Dial(ctx, "udp", net.JoinHostPort(host, port))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package global
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/Mzack9999/goja_nodejs/console"
|
||||
"github.com/Mzack9999/goja_nodejs/require"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/dop251/goja_nodejs/console"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
)
|
||||
|
||||
func TestScriptsRuntime(t *testing.T) {
|
||||
|
||||
+8
-59
@@ -1,13 +1,10 @@
|
||||
package gojs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"maps"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/Mzack9999/goja_nodejs/require"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
|
||||
)
|
||||
|
||||
@@ -50,65 +47,17 @@ func (p *GojaModule) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
// 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 {
|
||||
maps.Copy(p.sets, objects)
|
||||
|
||||
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 {
|
||||
|
||||
+2
-60
@@ -1,10 +1,7 @@
|
||||
package gojs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
errorutil "github.com/projectdiscovery/utils/errors"
|
||||
)
|
||||
|
||||
@@ -25,58 +22,6 @@ 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 {
|
||||
@@ -85,8 +30,5 @@ 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)
|
||||
}
|
||||
|
||||
// Wrap the function with context injection
|
||||
// wrappedFn := wrapWithContext(runtime, opts.FuncDecl)
|
||||
return runtime.Set(opts.Name, opts.FuncDecl /* wrappedFn */)
|
||||
return runtime.Set(opts.Name, opts.FuncDecl)
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package bytes
|
||||
import (
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/libs/structs"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
|
||||
)
|
||||
|
||||
+9
-12
@@ -1,7 +1,6 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
@@ -28,9 +27,8 @@ import (
|
||||
// // when no itemType is provided, it will return both files and directories
|
||||
// const items = fs.ListDir('/tmp');
|
||||
// ```
|
||||
func ListDir(ctx context.Context, path string, itemType string) ([]string, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
finalPath, err := protocolstate.NormalizePathWithExecutionId(executionId, path)
|
||||
func ListDir(path string, itemType string) ([]string, error) {
|
||||
finalPath, err := protocolstate.NormalizePath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -59,9 +57,8 @@ func ListDir(ctx context.Context, path string, itemType string) ([]string, error
|
||||
// // here permitted directories are $HOME/nuclei-templates/*
|
||||
// const content = fs.ReadFile('helpers/usernames.txt');
|
||||
// ```
|
||||
func ReadFile(ctx context.Context, path string) ([]byte, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
finalPath, err := protocolstate.NormalizePathWithExecutionId(executionId, path)
|
||||
func ReadFile(path string) ([]byte, error) {
|
||||
finalPath, err := protocolstate.NormalizePath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -77,8 +74,8 @@ func ReadFile(ctx context.Context, path string) ([]byte, error) {
|
||||
// // here permitted directories are $HOME/nuclei-templates/*
|
||||
// const content = fs.ReadFileAsString('helpers/usernames.txt');
|
||||
// ```
|
||||
func ReadFileAsString(ctx context.Context, path string) (string, error) {
|
||||
bin, err := ReadFile(ctx, path)
|
||||
func ReadFileAsString(path string) (string, error) {
|
||||
bin, err := ReadFile(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -94,14 +91,14 @@ func ReadFileAsString(ctx context.Context, path string) (string, error) {
|
||||
// const contents = fs.ReadFilesFromDir('helpers/ssh-keys');
|
||||
// log(contents);
|
||||
// ```
|
||||
func ReadFilesFromDir(ctx context.Context, dir string) ([]string, error) {
|
||||
files, err := ListDir(ctx, dir, "file")
|
||||
func ReadFilesFromDir(dir string) ([]string, error) {
|
||||
files, err := ListDir(dir, "file")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var results []string
|
||||
for _, file := range files {
|
||||
content, err := ReadFileAsString(ctx, dir+"/"+file)
|
||||
content, err := ReadFileAsString(dir + "/" + file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package goconsole
|
||||
|
||||
import (
|
||||
"github.com/Mzack9999/goja_nodejs/console"
|
||||
"github.com/dop251/goja_nodejs/console"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package kerberos
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/goja"
|
||||
kclient "github.com/jcmturner/gokrb5/v8/client"
|
||||
kconfig "github.com/jcmturner/gokrb5/v8/config"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
||||
@@ -109,8 +109,7 @@ func NewKerberosClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.O
|
||||
|
||||
if controller != "" {
|
||||
// validate controller hostport
|
||||
executionId := c.nj.ExecutionId()
|
||||
if !protocolstate.IsHostAllowed(executionId, controller) {
|
||||
if !protocolstate.IsHostAllowed(controller) {
|
||||
c.nj.Throw("domain controller address blacklisted by network policy")
|
||||
}
|
||||
|
||||
@@ -247,18 +246,16 @@ 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(executionId, kdc) {
|
||||
if !protocolstate.IsHostAllowed(kdc) {
|
||||
c.nj.Throw("KDC address %v blacklisted by network policy", kdc)
|
||||
}
|
||||
}
|
||||
for _, kpasswd := range r.KPasswdServer {
|
||||
if !protocolstate.IsHostAllowed(executionId, kpasswd) {
|
||||
if !protocolstate.IsHostAllowed(kpasswd) {
|
||||
c.nj.Throw("Kpasswd address %v blacklisted by network policy", kpasswd)
|
||||
}
|
||||
}
|
||||
@@ -268,7 +265,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(executionId, v) {
|
||||
if !protocolstate.IsHostAllowed(v) {
|
||||
c.nj.Throw("KDC address %v blacklisted by network policy", v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +68,6 @@ 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])
|
||||
@@ -81,14 +75,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 := dialers.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port))
|
||||
tcpConn, err := protocolstate.Dialer.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 {
|
||||
@@ -109,11 +103,6 @@ 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])
|
||||
@@ -121,14 +110,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 := dialers.Fastdialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port))
|
||||
udpConn, err := protocolstate.Dialer.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 {
|
||||
@@ -148,8 +137,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)
|
||||
@@ -169,8 +158,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)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Mzack9999/goja"
|
||||
"github.com/dop251/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,18 +86,12 @@ 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 = dialers.Fastdialer.Dial(context.TODO(), "unix", u.Path)
|
||||
conn, err = protocolstate.Dialer.Dial(context.TODO(), "unix", u.Path)
|
||||
c.nj.HandleError(err, "failed to connect to ldap server")
|
||||
} else {
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
@@ -116,12 +110,12 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object {
|
||||
if port == "" {
|
||||
port = ldap.DefaultLdapPort
|
||||
}
|
||||
conn, err = dialers.Fastdialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port))
|
||||
conn, err = protocolstate.Dialer.Dial(context.TODO(), "udp", net.JoinHostPort(host, port))
|
||||
case "ldap":
|
||||
if port == "" {
|
||||
port = ldap.DefaultLdapPort
|
||||
}
|
||||
conn, err = dialers.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port))
|
||||
conn, err = protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, port))
|
||||
case "ldaps":
|
||||
if port == "" {
|
||||
port = ldap.DefaultLdapsPort
|
||||
@@ -130,7 +124,7 @@ func NewClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object {
|
||||
if c.cfg.ServerName != "" {
|
||||
serverName = c.cfg.ServerName
|
||||
}
|
||||
conn, err = dialers.Fastdialer.DialTLSWithConfig(context.TODO(), "tcp", net.JoinHostPort(host, port),
|
||||
conn, err = protocolstate.Dialer.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)
|
||||
|
||||
@@ -10,11 +10,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
|
||||
func memoizedconnect(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(executionId, host, port, username, password, dbName)
|
||||
return connect(host, port, username, password, dbName)
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -26,11 +26,11 @@ func memoizedconnect(executionId string, host string, port int, username string,
|
||||
return false, errors.New("could not convert cached result")
|
||||
}
|
||||
|
||||
func memoizedisMssql(executionId string, host string, port int) (bool, error) {
|
||||
func memoizedisMssql(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(executionId, host, port)
|
||||
return isMssql(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
+20
-29
@@ -36,9 +36,8 @@ type (
|
||||
// const client = new mssql.MSSQLClient;
|
||||
// const connected = client.Connect('acme.com', 1433, 'username', 'password');
|
||||
// ```
|
||||
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")
|
||||
func (c *MSSQLClient) Connect(host string, port int, username, password string) (bool, error) {
|
||||
return memoizedconnect(host, port, username, password, "master")
|
||||
}
|
||||
|
||||
// ConnectWithDB connects to MS SQL database using given credentials and database name.
|
||||
@@ -51,17 +50,16 @@ func (c *MSSQLClient) Connect(ctx context.Context, host string, port int, userna
|
||||
// const client = new mssql.MSSQLClient;
|
||||
// const connected = client.ConnectWithDB('acme.com', 1433, 'username', 'password', 'master');
|
||||
// ```
|
||||
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)
|
||||
func (c *MSSQLClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) {
|
||||
return memoizedconnect(host, port, username, password, dbName)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func connect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
|
||||
func connect(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(executionId, host) {
|
||||
if !protocolstate.IsHostAllowed(host) {
|
||||
// host is not valid according to network policy
|
||||
return false, protocolstate.ErrHostDenied.Msgf(host)
|
||||
}
|
||||
@@ -79,8 +77,8 @@ func connect(executionId string, host string, port int, username string, passwor
|
||||
return false, err
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
_, err = db.Exec("select 1")
|
||||
if err != nil {
|
||||
@@ -109,30 +107,24 @@ func connect(executionId string, host string, port int, username string, passwor
|
||||
// const mssql = require('nuclei/mssql');
|
||||
// const isMssql = mssql.IsMssql('acme.com', 1433);
|
||||
// ```
|
||||
func (c *MSSQLClient) IsMssql(ctx context.Context, host string, port int) (bool, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
return memoizedisMssql(executionId, host, port)
|
||||
func (c *MSSQLClient) IsMssql(host string, port int) (bool, error) {
|
||||
return memoizedisMssql(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func isMssql(executionId string, host string, port int) (bool, error) {
|
||||
if !protocolstate.IsHostAllowed(executionId, host) {
|
||||
func isMssql(host string, port int) (bool, error) {
|
||||
if !protocolstate.IsHostAllowed(host) {
|
||||
// host is not valid according to network policy
|
||||
return false, protocolstate.ErrHostDenied.Msgf(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, fmt.Sprintf("%d", port)))
|
||||
conn, err := protocolstate.Dialer.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 {
|
||||
@@ -155,19 +147,18 @@ func isMssql(executionId string, 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(ctx context.Context, host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
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(executionId, host) {
|
||||
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))
|
||||
|
||||
ok, err := c.IsMssql(ctx, host, port)
|
||||
ok, err := c.IsMssql(host, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -186,8 +177,8 @@ func (c *MSSQLClient) ExecuteQuery(ctx context.Context, host string, port int, u
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
_ = db.Close()
|
||||
}()
|
||||
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(0)
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedisMySQL(executionId string, host string, port int) (bool, error) {
|
||||
func memoizedisMySQL(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(executionId, host, port)
|
||||
return isMySQL(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -24,11 +24,11 @@ func memoizedisMySQL(executionId string, host string, port int) (bool, error) {
|
||||
return false, errors.New("could not convert cached result")
|
||||
}
|
||||
|
||||
func memoizedfingerprintMySQL(executionId string, host string, port int) (MySQLInfo, error) {
|
||||
func memoizedfingerprintMySQL(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(executionId, host, port)
|
||||
return fingerprintMySQL(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return MySQLInfo{}, err
|
||||
|
||||
+27
-41
@@ -35,30 +35,24 @@ type (
|
||||
// const mysql = require('nuclei/mysql');
|
||||
// const isMySQL = mysql.IsMySQL('acme.com', 3306);
|
||||
// ```
|
||||
func (c *MySQLClient) IsMySQL(ctx context.Context, host string, port int) (bool, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
func (c *MySQLClient) IsMySQL(host string, port int) (bool, error) {
|
||||
// todo: why this is exposed? Service fingerprint should be automatic
|
||||
return memoizedisMySQL(executionId, host, port)
|
||||
return memoizedisMySQL(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func isMySQL(executionId string, host string, port int) (bool, error) {
|
||||
if !protocolstate.IsHostAllowed(executionId, host) {
|
||||
func isMySQL(host string, port int) (bool, error) {
|
||||
if !protocolstate.IsHostAllowed(host) {
|
||||
// host is not valid according to network policy
|
||||
return false, protocolstate.ErrHostDenied.Msgf(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, fmt.Sprintf("%d", port)))
|
||||
conn, err := protocolstate.Dialer.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})
|
||||
@@ -81,15 +75,14 @@ func isMySQL(executionId string, host string, port int) (bool, error) {
|
||||
// const client = new mysql.MySQLClient;
|
||||
// const connected = client.Connect('acme.com', 3306, 'username', 'password');
|
||||
// ```
|
||||
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) {
|
||||
func (c *MySQLClient) Connect(host string, port int, username, password string) (bool, error) {
|
||||
if !protocolstate.IsHostAllowed(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(ctx, host, port)
|
||||
ok, err := c.IsMySQL(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -134,30 +127,24 @@ type (
|
||||
// const info = mysql.FingerprintMySQL('acme.com', 3306);
|
||||
// log(to_json(info));
|
||||
// ```
|
||||
func (c *MySQLClient) FingerprintMySQL(ctx context.Context, host string, port int) (MySQLInfo, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
return memoizedfingerprintMySQL(executionId, host, port)
|
||||
func (c *MySQLClient) FingerprintMySQL(host string, port int) (MySQLInfo, error) {
|
||||
return memoizedfingerprintMySQL(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func fingerprintMySQL(executionId string, host string, port int) (MySQLInfo, error) {
|
||||
func fingerprintMySQL(host string, port int) (MySQLInfo, error) {
|
||||
info := MySQLInfo{}
|
||||
if !protocolstate.IsHostAllowed(executionId, host) {
|
||||
if !protocolstate.IsHostAllowed(host) {
|
||||
// host is not valid according to network policy
|
||||
return info, protocolstate.ErrHostDenied.Msgf(host)
|
||||
}
|
||||
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)))
|
||||
conn, err := protocolstate.Dialer.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})
|
||||
@@ -205,15 +192,14 @@ func (c *MySQLClient) ConnectWithDSN(dsn string) (bool, error) {
|
||||
// const result = mysql.ExecuteQueryWithOpts(options, 'SELECT * FROM users');
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
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) {
|
||||
func (c *MySQLClient) ExecuteQueryWithOpts(opts MySQLOptions, query string) (*utils.SQLResult, error) {
|
||||
if !protocolstate.IsHostAllowed(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(ctx, opts.Host, opts.Port)
|
||||
ok, err := c.IsMySQL(opts.Host, opts.Port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -231,8 +217,8 @@ func (c *MySQLClient) ExecuteQueryWithOpts(ctx context.Context, opts MySQLOption
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = db.Close()
|
||||
}()
|
||||
_ = db.Close()
|
||||
}()
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(0)
|
||||
|
||||
@@ -260,9 +246,9 @@ func (c *MySQLClient) ExecuteQueryWithOpts(ctx context.Context, opts MySQLOption
|
||||
// const result = mysql.ExecuteQuery('acme.com', 3306, 'username', 'password', 'SELECT * FROM users');
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
func (c *MySQLClient) ExecuteQuery(ctx context.Context, host string, port int, username, password, query string) (*utils.SQLResult, error) {
|
||||
func (c *MySQLClient) ExecuteQuery(host string, port int, username, password, query string) (*utils.SQLResult, error) {
|
||||
// executing queries implies the remote mysql service
|
||||
ok, err := c.IsMySQL(ctx, host, port)
|
||||
ok, err := c.IsMySQL(host, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -270,7 +256,7 @@ func (c *MySQLClient) ExecuteQuery(ctx context.Context, host string, port int, u
|
||||
return nil, fmt.Errorf("not a mysql service")
|
||||
}
|
||||
|
||||
return c.ExecuteQueryWithOpts(ctx, MySQLOptions{
|
||||
return c.ExecuteQueryWithOpts(MySQLOptions{
|
||||
Host: host,
|
||||
Port: port,
|
||||
Protocol: "tcp",
|
||||
@@ -287,8 +273,8 @@ func (c *MySQLClient) ExecuteQuery(ctx context.Context, host string, port int, u
|
||||
// const result = mysql.ExecuteQueryOnDB('acme.com', 3306, 'username', 'password', 'dbname', 'SELECT * FROM users');
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
func (c *MySQLClient) ExecuteQueryOnDB(ctx context.Context, host string, port int, username, password, dbname, query string) (*utils.SQLResult, error) {
|
||||
return c.ExecuteQueryWithOpts(ctx, MySQLOptions{
|
||||
func (c *MySQLClient) ExecuteQueryOnDB(host string, port int, username, password, dbname, query string) (*utils.SQLResult, error) {
|
||||
return c.ExecuteQueryWithOpts(MySQLOptions{
|
||||
Host: host,
|
||||
Port: port,
|
||||
Protocol: "tcp",
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+4
-15
@@ -25,13 +25,8 @@ var (
|
||||
// const net = require('nuclei/net');
|
||||
// const conn = net.Open('tcp', 'acme.com:80');
|
||||
// ```
|
||||
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)
|
||||
func Open(protocol, address string) (*NetConn, error) {
|
||||
conn, err := protocolstate.Dialer.Dial(context.TODO(), protocol, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -45,7 +40,7 @@ func Open(ctx context.Context, protocol, address string) (*NetConn, error) {
|
||||
// const net = require('nuclei/net');
|
||||
// const conn = net.OpenTLS('tcp', 'acme.com:443');
|
||||
// ```
|
||||
func OpenTLS(ctx context.Context, protocol, address string) (*NetConn, error) {
|
||||
func OpenTLS(protocol, address string) (*NetConn, error) {
|
||||
config := &tls.Config{InsecureSkipVerify: true, MinVersion: tls.VersionTLS10}
|
||||
host, _, _ := net.SplitHostPort(address)
|
||||
if host != "" {
|
||||
@@ -53,13 +48,7 @@ func OpenTLS(ctx context.Context, protocol, address string) (*NetConn, error) {
|
||||
c.ServerName = host
|
||||
config = c
|
||||
}
|
||||
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)
|
||||
conn, err := protocolstate.Dialer.DialTLSWithConfig(context.TODO(), protocol, address, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedisOracle(executionId string, host string, port int) (IsOracleResponse, error) {
|
||||
func memoizedisOracle(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(executionId, host, port)
|
||||
return isOracle(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return IsOracleResponse{}, err
|
||||
|
||||
@@ -2,7 +2,6 @@ package oracle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -33,22 +32,16 @@ type (
|
||||
// const isOracle = oracle.IsOracle('acme.com', 1521);
|
||||
// log(toJSON(isOracle));
|
||||
// ```
|
||||
func IsOracle(ctx context.Context, host string, port int) (IsOracleResponse, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
return memoizedisOracle(executionId, host, port)
|
||||
func IsOracle(host string, port int) (IsOracleResponse, error) {
|
||||
return memoizedisOracle(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func isOracle(executionId string, host string, port int) (IsOracleResponse, error) {
|
||||
func isOracle(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 := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
|
||||
conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedisPoP3(executionId string, host string, port int) (IsPOP3Response, error) {
|
||||
func memoizedisPoP3(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(executionId, host, port)
|
||||
return isPoP3(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return IsPOP3Response{}, err
|
||||
|
||||
@@ -2,7 +2,6 @@ package pop3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -34,22 +33,16 @@ type (
|
||||
// const isPOP3 = pop3.IsPOP3('acme.com', 110);
|
||||
// log(toJSON(isPOP3));
|
||||
// ```
|
||||
func IsPOP3(ctx context.Context, host string, port int) (IsPOP3Response, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
return memoizedisPoP3(executionId, host, port)
|
||||
func IsPOP3(host string, port int) (IsPOP3Response, error) {
|
||||
return memoizedisPoP3(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func isPoP3(executionId string, host string, port int) (IsPOP3Response, error) {
|
||||
func isPoP3(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 := dialer.Fastdialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
|
||||
conn, err := protocolstate.Dialer.Dial(context.TODO(), "tcp", net.JoinHostPort(host, strconv.Itoa(port)))
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedisPostgres(executionId string, host string, port int) (bool, error) {
|
||||
func memoizedisPostgres(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(executionId, host, port)
|
||||
return isPostgres(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -28,11 +28,11 @@ func memoizedisPostgres(executionId string, host string, port int) (bool, error)
|
||||
return false, errors.New("could not convert cached result")
|
||||
}
|
||||
|
||||
func memoizedexecuteQuery(executionId string, host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) {
|
||||
func memoizedexecuteQuery(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(executionId, host, port, username, password, dbName, query)
|
||||
return executeQuery(host, port, username, password, dbName, query)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -44,11 +44,11 @@ func memoizedexecuteQuery(executionId string, host string, port int, username st
|
||||
return nil, errors.New("could not convert cached result")
|
||||
}
|
||||
|
||||
func memoizedconnect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
|
||||
func memoizedconnect(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(executionId, host, port, username, password, dbName)
|
||||
return connect(host, port, username, password, dbName)
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
@@ -36,28 +36,22 @@ type (
|
||||
// const postgres = require('nuclei/postgres');
|
||||
// const isPostgres = postgres.IsPostgres('acme.com', 5432);
|
||||
// ```
|
||||
func (c *PGClient) IsPostgres(ctx context.Context, host string, port int) (bool, error) {
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
func (c *PGClient) IsPostgres(host string, port int) (bool, error) {
|
||||
// todo: why this is exposed? Service fingerprint should be automatic
|
||||
return memoizedisPostgres(executionId, host, port)
|
||||
return memoizedisPostgres(host, port)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func isPostgres(executionId string, host string, port int) (bool, error) {
|
||||
func isPostgres(host string, port int) (bool, error) {
|
||||
timeout := 10 * time.Second
|
||||
|
||||
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))
|
||||
conn, err := protocolstate.Dialer.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))
|
||||
|
||||
@@ -82,16 +76,15 @@ func isPostgres(executionId string, host string, port int) (bool, error) {
|
||||
// const client = new postgres.PGClient;
|
||||
// const connected = client.Connect('acme.com', 5432, 'username', 'password');
|
||||
// ```
|
||||
func (c *PGClient) Connect(ctx context.Context, host string, port int, username, password string) (bool, error) {
|
||||
ok, err := c.IsPostgres(ctx, host, port)
|
||||
func (c *PGClient) Connect(host string, port int, username, password string) (bool, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
return memoizedconnect(executionId, host, port, username, password, "postgres")
|
||||
return memoizedconnect(host, port, username, password, "postgres")
|
||||
}
|
||||
|
||||
// ExecuteQuery connects to Postgres database using given credentials and database name.
|
||||
@@ -104,8 +97,8 @@ func (c *PGClient) Connect(ctx context.Context, host string, port int, username,
|
||||
// const result = client.ExecuteQuery('acme.com', 5432, 'username', 'password', 'dbname', 'select * from users');
|
||||
// log(to_json(result));
|
||||
// ```
|
||||
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)
|
||||
func (c *PGClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -113,28 +106,26 @@ func (c *PGClient) ExecuteQuery(ctx context.Context, host string, port int, user
|
||||
return nil, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
|
||||
return memoizedexecuteQuery(executionId, host, port, username, password, dbName, query)
|
||||
return memoizedexecuteQuery(host, port, username, password, dbName, query)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func executeQuery(executionId string, host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) {
|
||||
if !protocolstate.IsHostAllowed(executionId, host) {
|
||||
func executeQuery(host string, port int, username string, password string, dbName string, query string) (*utils.SQLResult, error) {
|
||||
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))
|
||||
|
||||
connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable&executionId=%s", username, password, target, dbName, executionId)
|
||||
connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", username, password, target, dbName)
|
||||
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 {
|
||||
@@ -157,8 +148,8 @@ func executeQuery(executionId string, host string, port int, username string, pa
|
||||
// const client = new postgres.PGClient;
|
||||
// const connected = client.ConnectWithDB('acme.com', 5432, 'username', 'password', 'dbname');
|
||||
// ```
|
||||
func (c *PGClient) ConnectWithDB(ctx context.Context, host string, port int, username, password, dbName string) (bool, error) {
|
||||
ok, err := c.IsPostgres(ctx, host, port)
|
||||
func (c *PGClient) ConnectWithDB(host string, port int, username, password, dbName string) (bool, error) {
|
||||
ok, err := c.IsPostgres(host, port)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -166,18 +157,16 @@ func (c *PGClient) ConnectWithDB(ctx context.Context, host string, port int, use
|
||||
return false, fmt.Errorf("not a postgres service")
|
||||
}
|
||||
|
||||
executionId := ctx.Value("executionId").(string)
|
||||
|
||||
return memoizedconnect(executionId, host, port, username, password, dbName)
|
||||
return memoizedconnect(host, port, username, password, dbName)
|
||||
}
|
||||
|
||||
// @memo
|
||||
func connect(executionId string, host string, port int, username string, password string, dbName string) (bool, error) {
|
||||
func connect(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(executionId, host) {
|
||||
if !protocolstate.IsHostAllowed(host) {
|
||||
// host is not valid according to network policy
|
||||
return false, protocolstate.ErrHostDenied.Msgf(host)
|
||||
}
|
||||
@@ -187,24 +176,19 @@ func connect(executionId string, host string, port int, username string, passwor
|
||||
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 dialer.Fastdialer.Dial(context.Background(), network, addr)
|
||||
return protocolstate.Dialer.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 {
|
||||
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
|
||||
)
|
||||
|
||||
func memoizedisRDP(executionId string, host string, port int) (IsRDPResponse, error) {
|
||||
func memoizedisRDP(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(executionId, host, port)
|
||||
return isRDP(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return IsRDPResponse{}, err
|
||||
@@ -24,11 +24,11 @@ func memoizedisRDP(executionId string, host string, port int) (IsRDPResponse, er
|
||||
return IsRDPResponse{}, errors.New("could not convert cached result")
|
||||
}
|
||||
|
||||
func memoizedcheckRDPAuth(executionId string, host string, port int) (CheckRDPAuthResponse, error) {
|
||||
func memoizedcheckRDPAuth(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(executionId, host, port)
|
||||
return checkRDPAuth(host, port)
|
||||
})
|
||||
if err != nil {
|
||||
return CheckRDPAuthResponse{}, err
|
||||
|
||||
Loaded 100 of 207 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user