From 4d2327274bca779a836dfd90961c7ae3dbca70be Mon Sep 17 00:00:00 2001 From: Eshan Singh <32596297+R0X4R@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:24:40 +0530 Subject: [PATCH 1/5] fix: resolve project paths using script location Use the script's real location as the base path for loading libraries, modules, and configuration files. This prevents path resolution issues when the script is executed from different directories and ensures project resources are loaded consistently. --- Makefile | 34 +++++++++++++++++++++++++ README.md | 16 ++++++------ cmd/api.go | 41 ++++++------------------------ cmd/requester.go | 26 +++++++++---------- cmd/root.go | 66 +++++++++++++++++++++++++++++++++--------------- 5 files changed, 109 insertions(+), 74 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5139efc --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +.PHONY: install build + +TARGET_DIR = $(HOME)/.nomore403/payloads +REPO_URL = https://raw.githubusercontent.com/devploit/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/devploit/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..e2c4740 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/devploit/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/devploit/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()) } From c5b539c012d7e5cba109b93a2048cf9c928dfecf Mon Sep 17 00:00:00 2001 From: Eshan Singh <32596297+R0X4R@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:30:27 +0530 Subject: [PATCH 2/5] my repo just for test This is just a test commit to install nomore403 in my device --- Makefile | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5139efc..efffe22 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: install build TARGET_DIR = $(HOME)/.nomore403/payloads -REPO_URL = https://raw.githubusercontent.com/devploit/nomore403/main/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. @@ -20,7 +20,7 @@ install: curl -sSL "$(REPO_URL)/$$file" -o "$(TARGET_DIR)/$$file"; \ done @echo "[*] INSTALLING nomore403" - @go install github.com/devploit/nomore403@latest + @go install github.com/R0X4R/nomore403@latest @echo "[+] SUCCESS! nomore403 IS INSTALLED." @$(GOBIN)/nomore403 -h diff --git a/README.md b/README.md index e2c4740..514c551 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ This tool does not "break authentication" by itself. It helps find differences b 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 -curl -sSL https://raw.githubusercontent.com/devploit/nomore403/main/Makefile | make -f - install +curl -sSL https://raw.githubusercontent.com/R0X4R/nomore403/main/Makefile | make -f - install ``` ### Local Build from Source @@ -56,7 +56,7 @@ curl -sSL https://raw.githubusercontent.com/devploit/nomore403/main/Makefile | m 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 -git clone https://github.com/devploit/nomore403 && cd nomore403 && make build +git clone https://github.com/R0X4R/nomore403 && cd nomore403 && make build ``` ## Requirements From 976d52dd825a554a0d7c592f6973c1b2a2da6405 Mon Sep 17 00:00:00 2001 From: Eshan Singh <32596297+R0X4R@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:32:32 +0530 Subject: [PATCH 3/5] Update go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 37fd1be..5bcb4bc 100755 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/devploit/nomore403 +module github.com/R0X4R/nomore403 go 1.24.0 From 4381c507e988258d49d86885b9654387051d9eb6 Mon Sep 17 00:00:00 2001 From: Eshan Singh <32596297+R0X4R@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:35:16 +0530 Subject: [PATCH 4/5] Update main.go --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ( From d2b9105e965f3657f747c4a593328c2291ed551c Mon Sep 17 00:00:00 2001 From: Eshan Singh <32596297+R0X4R@users.noreply.github.com> Date: Mon, 15 Jun 2026 23:39:41 +0530 Subject: [PATCH 5/5] new --- go.mod | 27 +++++++++++++-------------- go.sum | 53 +++++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index 5bcb4bc..ae2a843 100755 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ 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=