diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..efffe22 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +.PHONY: install build + +TARGET_DIR = $(HOME)/.nomore403/payloads +REPO_URL = https://raw.githubusercontent.com/R0X4R/nomore403/main/payloads +FILES = endpaths headers httpmethods ips midpaths simpleheaders useragents + +# Dynamically resolve GOBIN using Go's environment variables. +# If GOBIN is empty, Go defaults to using GOPATH/bin. +GOBIN := $(shell go env GOBIN) +namespace :; +ifeq ($(GOBIN),) + GOBIN := $(shell go env GOPATH)/bin +endif + +install: + @echo "[*] ENSURING GLOBAL CONFIGURATION DIRECTORIES EXIST" + @mkdir -p $(TARGET_DIR) + @echo "[*] DOWNLOADING ASSET PAYLOADS FROM GITHUB REPOSITORY" + @for file in $(FILES); do \ + curl -sSL "$(REPO_URL)/$$file" -o "$(TARGET_DIR)/$$file"; \ + done + @echo "[*] INSTALLING nomore403" + @go install github.com/R0X4R/nomore403@latest + @echo "[+] SUCCESS! nomore403 IS INSTALLED." + @$(GOBIN)/nomore403 -h + +build: + @echo "[*] ENSURING GLOBAL CONFIGURATION DIRECTORIES EXIST" + @mkdir -p $(TARGET_DIR) + @echo "[*] DEPLOYING LOCAL PAYLOADS" + @cp -r payloads/* $(TARGET_DIR)/ + @echo "[*] BUILDING LOCAL BINARY" + @go build -o nomore403 main.go + @$(HOME)/go/bin/nomore403 -h diff --git a/README.md b/README.md index e00c4ee..514c551 100644 --- a/README.md +++ b/README.md @@ -43,22 +43,22 @@ This tool does not "break authentication" by itself. It helps find differences b ## Installation -### Build from source +### Global Installation (Zero Download) + +If you want to install the tool globally without cloning the repository or downloading any files manually, run this one-liner. It pulls the setup configuration, deploys the required asset payloads to your home directory, and installs the binary system-wide. ```bash -git clone https://github.com/devploit/nomore403 -cd nomore403 -go build +curl -sSL https://raw.githubusercontent.com/R0X4R/nomore403/main/Makefile | make -f - install ``` -### Install with Go +### Local Build from Source + +Use this method if you want to inspect the source code, modify the project, or build a local executable binary inside your current working directory. ```bash -go install github.com/devploit/nomore403@latest +git clone https://github.com/R0X4R/nomore403 && cd nomore403 && make build ``` -If you install with `go install`, the `payloads/` directory is not installed automatically. Clone the repository and point the tool to that directory with `-f` if needed. - ## Requirements - Go 1.24 or later to build from source diff --git a/cmd/api.go b/cmd/api.go index 5a64b38..421b251 100755 --- a/cmd/api.go +++ b/cmd/api.go @@ -168,7 +168,7 @@ func isTransientError(err error) bool { "connection reset", "EOF", "temporary failure", - "no such host", // DNS can be transient + "no such host", } for _, pattern := range transientPatterns { if strings.Contains(strings.ToLower(errStr), strings.ToLower(pattern)) { @@ -178,11 +178,6 @@ func isTransientError(err error) bool { return false } -// request makes a single HTTP request using headers `headers` and proxy `proxy`. -func request(method, uri string, headers []header, proxy *url.URL, timeout int, redirect bool) (ResponseInfo, error) { - return requestBody(method, uri, headers, "", proxy, timeout, redirect) -} - func requestBody(method, uri string, headers []header, body string, proxy *url.URL, timeout int, redirect bool) (ResponseInfo, error) { if method == "" { method = "GET" @@ -192,8 +187,6 @@ func requestBody(method, uri string, headers []header, body string, proxy *url.U proxy = nil } - // net/http and url.Parse do not accept legacy IIS-style %uXXXX escapes. - // Route those requests through the raw client so the request target is sent as-is. if strings.Contains(strings.ToLower(uri), "%u") && proxy == nil && !redirect { return rawRequest(method, uri, rawRequestTarget(uri), headers, body, timeout) } @@ -202,9 +195,6 @@ func requestBody(method, uri string, headers []header, body string, proxy *url.U parsedURL, err := url.Parse(uri) if err != nil || parsedURL == nil || parsedURL.Scheme == "" || parsedURL.Host == "" { - // Fallback for non-standard encoding (e.g., %u002f unicode escapes) - // that url.Parse rejects. Extract scheme/host manually and preserve - // the raw path so the server receives it as-is. parsedURL, err = parseRawURL(uri) if err != nil { return ResponseInfo{}, fmt.Errorf("invalid URL: %q", uri) @@ -222,8 +212,6 @@ func requestBody(method, uri string, headers []header, body string, proxy *url.U req.Header = make(http.Header) for _, header := range headers { - // Go's net/http ignores req.Header["Host"] — it uses req.Host instead. - // Set req.Host directly so Host header variations are actually sent. if strings.EqualFold(header.key, "Host") { req.Host = header.value } else { @@ -261,7 +249,6 @@ func requestBody(method, uri string, headers []header, body string, proxy *url.U // loadFlagsFromRequestFile parse an HTTP request and configure the necessary flags for an execution func loadFlagsFromRequestFile(requestFile string, schema bool, verbose bool, techniques []string, redirect bool) { - // Read the content of the request file content, err := os.ReadFile(requestFile) if err != nil { log.Printf("[!] Error reading request file: %v", err) @@ -274,7 +261,6 @@ func loadFlagsFromRequestFile(requestFile string, schema bool, verbose bool, tec return } - // Down HTTP/2 to HTTP/1.1 (handles both "HTTP/2" and "HTTP/2.0") firstLine := temp[0] if strings.Contains(firstLine, "HTTP/2.0") { firstLine = strings.Replace(firstLine, "HTTP/2.0", "HTTP/1.1", 1) @@ -304,7 +290,6 @@ func loadFlagsFromRequestFile(requestFile string, schema bool, verbose bool, tec uri := httpSchema + req.Host + req.RequestURI - // Extract headers from the request var reqHeaders []string for k, v := range req.Header { reqHeaders = append(reqHeaders, k+": "+strings.Join(v, "")) @@ -320,10 +305,8 @@ func runAutocalibrate(options RequestOptions) (int, int) { calibrationPaths := []string{"calibration_test_123456", "calib_nonexist_789xyz", "zz_calibrate_000"} var samples []int - baseURI := options.uri - if !strings.HasSuffix(baseURI, "/") { - baseURI += "/" - } + // Unconditionally ensure there is exactly one trailing slash + baseURI := strings.TrimSuffix(options.uri, "/") + "/" var lastStatusCode int for _, path := range calibrationPaths { @@ -342,7 +325,6 @@ func runAutocalibrate(options RequestOptions) (int, int) { return 0, 0 } - // Calculate average and max deviation sum := 0 for _, s := range samples { sum += s @@ -360,19 +342,13 @@ func runAutocalibrate(options RequestOptions) (int, int) { } } - // Use tolerance = max(calibrationTolerance, maxDeviation*2) to handle dynamic content tolerance := calibrationTolerance if maxDeviation*2 > tolerance { tolerance = maxDeviation * 2 } - // Fragment calibration: request URI#fragment to baseline fragment-stripped responses. - // Since # is a fragment separator, the server receives the parent path instead of the - // target path. This catches false positives from any payload that accidentally creates - // a fragment URL (e.g., midpath "#" → domain.com/#path → requests domain.com/). parsedURI, parseErr := url.Parse(options.uri) if parseErr == nil && parsedURI.Path != "" && parsedURI.Path != "/" { - // Build parent path: /api/admin → /api/ parentPath := parsedURI.Path if strings.HasSuffix(parentPath, "/") { parentPath = parentPath[:len(parentPath)-1] @@ -392,7 +368,7 @@ func runAutocalibrate(options RequestOptions) (int, int) { if getFragmentCl() > 0 { summary += fmt.Sprintf(" | frag %db", getFragmentCl()) } - fmt.Printf("\n%s %s\n", color.New(color.FgHiBlack, color.Bold).Sprint("calib:"), color.New(color.FgHiBlack).Sprint(summary)) + fmt.Printf("\n%s %s\n", color.New(color.FgHiYellow, color.Bold).Sprint("CALIB:"), color.New(color.FgHiYellow).Sprint(summary)) return avgCl, tolerance } @@ -425,7 +401,6 @@ func parseRawURL(rawURI string) (*url.URL, error) { return nil, fmt.Errorf("missing host") } - // Split raw path and query rawQuery := "" if qIdx := strings.Index(rawPath, "?"); qIdx >= 0 { rawQuery = rawPath[qIdx+1:] @@ -433,10 +408,10 @@ func parseRawURL(rawURI string) (*url.URL, error) { } return &url.URL{ - Scheme: scheme, - Host: host, - Opaque: rawPath, - RawQuery: rawQuery, + Scheme: scheme, + Host: host, + Opaque: rawPath, + RawQuery: rawQuery, }, nil } diff --git a/cmd/requester.go b/cmd/requester.go index d027a4e..72a558b 100755 --- a/cmd/requester.go +++ b/cmd/requester.go @@ -370,7 +370,7 @@ func colorizeStatusTransition(result Result) string { if statusPriority(result.statusCode) > statusPriority(base) { arrow = color.GreenString("=>") } else if statusPriority(result.statusCode) < statusPriority(base) { - arrow = color.HiBlackString("->") + arrow = color.HiWhiteString("->") } return fmt.Sprintf("%s%s%s", colorizeStatusCode(base), arrow, colorizeStatusCode(result.statusCode)) @@ -1077,7 +1077,7 @@ func printFindingGroup(findings []Result, limit int, includeCurl bool) { limit = len(collapsed) } for i, f := range collapsed[:limit] { - scoreColor := color.New(color.FgHiBlack) + scoreColor := color.New(color.FgHiMagenta) techColor := color.New(color.FgWhite, color.Bold) marker := " " switch f.likelihood { @@ -1159,10 +1159,10 @@ func colorizeWhyText(text string) string { "location changed", color.CyanString("location changed"), "redirect anomaly", color.CyanString("redirect anomaly"), "type changed", color.MagentaString("type changed"), - "server changed", color.HiBlackString("server changed"), + "server changed", color.HiWhiteString("server changed"), "len Δ", color.BlueString("len Δ"), "unstable replay", color.MagentaString("unstable replay"), - "minor variation", color.HiBlackString("minor variation"), + "minor variation", color.HiWhiteString("minor variation"), ) return replacer.Replace(text) } @@ -1245,8 +1245,8 @@ func printSilentTechniqueSummary() { return } fmt.Printf("\n%s %s\n", - color.New(color.FgHiBlack, color.Bold).Sprint("no visible results:"), - color.New(color.FgHiBlack).Sprintf("%d techniques", len(silent)), + color.New(color.FgHiWhite, color.Bold).Sprint("no visible results:"), + color.New(color.FgHiWhite).Sprintf("%d techniques", len(silent)), ) } @@ -1480,7 +1480,7 @@ func formatPrintedResult(result Result) string { itemWidth := terminalWidth() - 2 - techWidth - 1 - scoreWidth - 1 - codeWidth - 1 - sizeWidth - 2 item := truncateForDisplay(result.line, itemWidth) if result.defaultReq { - techDefault := color.New(color.FgHiBlack, color.Bold).Sprintf("%-*s", techWidth, "default") + techDefault := color.New(color.FgHiWhite, color.Bold).Sprintf("%-*s", techWidth, "default") scoreBlank := strings.Repeat(" ", scoreWidth) return fmt.Sprintf(" %s %s %s %s %s", techDefault, scoreBlank, statusLabel, clStr, item) } @@ -1495,7 +1495,7 @@ func scoreColPlaceholder() string { func formatCompactScore(score int, likelihood string) string { marker := "." - style := color.New(color.FgHiBlack) + style := color.New(color.FgHiWhite) switch likelihood { case "medium": marker = "+" @@ -1606,16 +1606,16 @@ func showInfo(options RequestOptions) { if targetWidth < 36 { targetWidth = 36 } - labelStyle := color.New(color.FgHiBlack, color.Bold).SprintFunc() + labelStyle := color.New(color.FgHiWhite, color.Bold).SprintFunc() valueStyle := color.New(color.FgWhite, color.Bold).SprintFunc() meta := []string{ - labelStyle("target:") + " " + valueStyle(truncateForDisplay(options.uri, targetWidth)), - labelStyle("method:") + " " + valueStyle(options.method), + labelStyle("TARGET:") + " " + valueStyle(truncateForDisplay(options.uri, targetWidth)), + labelStyle("METHOD:") + " " + valueStyle(options.method), } if len(options.frontendHints) > 0 { - meta = append(meta, labelStyle("frontend:")+" "+valueStyle(strings.Join(options.frontendHints, ", "))) + meta = append(meta, labelStyle("FRONTEND:")+" "+valueStyle(strings.Join(options.frontendHints, ", "))) } - meta = append(meta, labelStyle("payloads:")+" "+valueStyle(options.folder)) + meta = append(meta, labelStyle("PAYLOADS:")+" "+valueStyle(options.folder)) fmt.Println(strings.Join(meta, " ")) } diff --git a/cmd/root.go b/cmd/root.go index 7f2af64..f04fe33 100755 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,6 +7,7 @@ import ( "log" "net/url" "os" + "path/filepath" "strings" "time" @@ -14,6 +15,7 @@ import ( "github.com/spf13/viper" ) +// Global configuration variables assigned via Cobra command line flags. var ( bypassIP string cfgFile string @@ -52,19 +54,45 @@ var ( techniqueExplicit bool ) -// rootCmd represents the base command when called without any subcommands +// rootCmd represents the base command when called without any subcommands. var rootCmd = &cobra.Command{ Use: "nomore403", Short: "Tool to bypass 40X response codes.", Long: `Command line application that automates different ways to bypass 40X codes.`, Run: func(cmd *cobra.Command, args []string) { + // Verify if the user explicitly provided the technique flag. techniqueExplicit = cmd.Flags().Changed("technique") + + // Resolve the correct directory path for loading assets when none is given. if len(folder) == 0 { - folder = "payloads" + // First choice: Check for the folder deployed into the home directory. + home, err := os.UserHomeDir() + if err == nil { + globalPath := filepath.Join(home, ".nomore403", "payloads") + if _, err := os.Stat(globalPath); err == nil { + folder = globalPath + } + } + + // Second choice: Look right next to the physical location of the running binary. + if len(folder) == 0 { + execPath, err := os.Executable() + if err != nil { + log.Printf("[!] Error getting executable path: %v", err) + folder = "payloads" + } else { + // Follow symlinks to locate the true folder rather than the link file location. + realExecPath, err := filepath.EvalSymlinks(execPath) + if err != nil { + realExecPath = execPath + } + folder = filepath.Join(filepath.Dir(realExecPath), "payloads") + } + } } - // Initialize output writer if -o flag is set + // Initialize output writer if -o flag is set. if outputFile != "" { if err := initOutputWriter(outputFile); err != nil { log.Printf("[!] Error opening output file: %v", err) @@ -73,14 +101,15 @@ var rootCmd = &cobra.Command{ defer closeOutputWriter() } + // Check standard input status to determine if targets are being piped into the tool. fi, err := os.Stdin.Stat() if err != nil { log.Printf("[!] Error reading stdin: %v", err) return } - // Ensure JSON output is flushed at the end if writing to stdout defer flushJSONToStdout() + // If data is detected in standard input, parse it row by row. if (fi.Mode() & os.ModeCharDevice) == 0 { bytes, err := io.ReadAll(os.Stdin) if err != nil { @@ -98,6 +127,7 @@ var rootCmd = &cobra.Command{ } runTargets(urls) } else { + // If stdin is empty, fallback to reading raw request files or the target URI flag. if len(requestFile) > 0 { loadFlagsFromRequestFile(requestFile, schema, verbose, technique, redirect) } else { @@ -105,7 +135,7 @@ var rootCmd = &cobra.Command{ _ = cmd.Help() return } - // Check if -u value is a file containing URLs + // The input URI can be a direct target or a pointer to a file containing a target list. urls := readURLsFromInput(uri) runTargets(urls) } @@ -120,7 +150,6 @@ func SetVersionInfo(version, buildDate string) { } // Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { cobra.CheckErr(rootCmd.Execute()) } @@ -128,6 +157,7 @@ func Execute() { func init() { cobra.OnInitialize(initConfig) + // Command flags declaration mapping terminal options to global variables. rootCmd.PersistentFlags().StringVarP(&bypassIP, "bypass-ip", "i", "", "Use a specified IP address or hostname for bypassing access controls. Injects this IP in headers like 'X-Forwarded-For'.") rootCmd.PersistentFlags().IntVarP(&delay, "delay", "d", 0, "Specify a delay between requests in milliseconds. Helps manage request rate (default: 0ms).") rootCmd.PersistentFlags().StringVarP(&folder, "folder", "f", "", "Specify the folder location for payloads if not in the same directory as the executable.") @@ -163,6 +193,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&payloadPosition, "payload-position", "p", "", "Marker in URL indicating where to insert payloads (e.g., §). Use in URL like: -u 'http://example.com/§100§/admin'.") } +// runTargets loops through identified endpoints and triggers the analysis engine. func runTargets(urls []string) { lastHostRun := make(map[string]time.Time) @@ -172,6 +203,7 @@ func runTargets(urls []string) { continue } + // Apply host throttling structures if a user-defined host delay exists. if hostDelayMs > 0 { if parsed, err := url.Parse(target); err == nil && parsed.Host != "" { if lastRun, ok := lastHostRun[parsed.Host]; ok { @@ -188,18 +220,16 @@ func runTargets(urls []string) { } } -// readURLsFromInput checks if the input is a file path containing URLs. -// If it is, returns all URLs from the file. Otherwise returns the input as a single URL. +// readURLsFromInput parses target entries from direct input strings or text line collections. func readURLsFromInput(input string) []string { - // If input looks like a URL (has scheme), treat it as a single URL + // If input string matches an HTTP protocol pattern, treat it as an isolated target. if strings.HasPrefix(input, "http://") || strings.HasPrefix(input, "https://") { return []string{input} } - // Try to open as a file + // Attempt opening the path assuming it is a text list file containing targets. file, err := os.Open(input) if err != nil { - // Not a file, treat as a URL return []string{input} } defer file.Close() @@ -226,25 +256,21 @@ func readURLsFromInput(input string) []string { return urls } -// initConfig reads in config file and ENV variables if set. +// initConfig reads in configuration parameters from setup files and environment profiles. func initConfig() { + home, err := os.UserHomeDir() + cobra.CheckErr(err) + if cfgFile != "" { - // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { - // Find home directory. - home, err := os.UserHomeDir() - cobra.CheckErr(err) - - // Search config in home directory with name ".nomore403" (without extension). viper.AddConfigPath(home) viper.SetConfigType("yaml") viper.SetConfigName(".nomore403") } - viper.AutomaticEnv() // read in environment variables that match + viper.AutomaticEnv() - // If a config file is found, read it in. if err := viper.ReadInConfig(); err == nil { fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) } diff --git a/go.mod b/go.mod index 37fd1be..ae2a843 100755 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ -module github.com/devploit/nomore403 +module github.com/R0X4R/nomore403 -go 1.24.0 +go 1.26.3 require ( - github.com/fatih/color v1.18.0 - github.com/spf13/cobra v1.9.1 - github.com/spf13/viper v1.20.1 + github.com/fatih/color v1.19.0 + github.com/spf13/cobra v1.10.2 + github.com/spf13/viper v1.21.0 github.com/zenthangplus/goccm v1.1.3 - golang.org/x/term v0.40.0 + golang.org/x/term v0.44.0 ) require ( @@ -17,14 +17,13 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/text v0.24.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.28.0 // indirect ) diff --git a/go.sum b/go.sum index 35c31b0..e54c48a 100755 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/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.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= @@ -28,35 +28,36 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= -github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/zenthangplus/goccm v1.1.3 h1:66XVj24yexO2fCkBum8b+y6tOJ7Giq05LIn2vn3whGE= github.com/zenthangplus/goccm v1.1.3/go.mod h1:DUzu/BC4TkgUfXP8J1P6Md73Djt+0l0CHq001Pt4weA= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= -golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc= +golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index 767fe9c..6a69941 100755 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main -import "github.com/devploit/nomore403/cmd" +import "github.com/R0X4R/nomore403/cmd" // Version and BuildDate are set via ldflags at build time. var (