From b5b5bbaeae75c5c8162fa09ad1c602a614608314 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:49:11 +0000 Subject: [PATCH 01/12] Initial plan From 26316fab8dc712e54fbc29031a5732dcc64bf385 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:53:15 +0000 Subject: [PATCH 02/12] Add support for importing URLs from file with -file flag Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- main.go | 169 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 128 insertions(+), 41 deletions(-) diff --git a/main.go b/main.go index 188aec7..f7e0126 100755 --- a/main.go +++ b/main.go @@ -32,6 +32,7 @@ type config struct { outdir string // output directory url string // sourcemap url jsurl string // javascript url + file string // file containing URLs proxy string // upstream proxy server insecure bool // skip tls verification headers headerList // additional user-supplied http headers @@ -277,27 +278,106 @@ func cleanWindows(p string) string { return m1.ReplaceAllString(p, "") } +// readURLsFromFile reads URLs from a file, one URL per line +func readURLsFromFile(filepath string) ([]string, error) { + file, err := os.Open(filepath) + if err != nil { + return nil, err + } + defer file.Close() + + var urls []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + // Skip empty lines and comments + if line != "" && !strings.HasPrefix(line, "#") { + urls = append(urls, line) + } + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return urls, nil +} + +// processSourceMap processes a single sourcemap and writes its sources to disk +func processSourceMap(sm sourceMap, outdir string) error { + log.Printf("[+] Retrieved Sourcemap with version %d, containing %d entries.\n", sm.Version, len(sm.Sources)) + + if len(sm.Sources) == 0 { + return errors.New("no sources found") + } + + if len(sm.SourcesContent) == 0 { + return errors.New("no source content found") + } + + if sm.Version != 3 { + log.Println("[!] Sourcemap is not version 3. This is untested!") + } + + if _, err := os.Stat(outdir); os.IsNotExist(err) { + err = os.Mkdir(outdir, 0700) + if err != nil { + return err + } + } + + for i, sourcePath := range sm.Sources { + sourcePath = "/" + sourcePath // path.Clean will ignore a leading '..', must be a '/..' + // If on windows, clean the sourcepath. + if runtime.GOOS == "windows" { + sourcePath = cleanWindows(sourcePath) + } + + // Use filepath.Join. https://parsiya.net/blog/2019-03-09-path.join-considered-harmful/ + scriptPath, scriptData := filepath.Join(outdir, filepath.Clean(sourcePath)), sm.SourcesContent[i] + err := writeFile(scriptPath, scriptData) + if err != nil { + log.Printf("Error writing %s file: %s", scriptPath, err) + } + } + + return nil +} + func main() { var proxyURL url.URL var conf config var err error flag.StringVar(&conf.outdir, "output", "", "Source file output directory - REQUIRED") - flag.StringVar(&conf.url, "url", "", "URL or path to the Sourcemap file - cannot be used with jsurl") - flag.StringVar(&conf.jsurl, "jsurl", "", "URL to JavaScript file - cannot be used with url") + flag.StringVar(&conf.url, "url", "", "URL or path to the Sourcemap file - cannot be used with jsurl or file") + flag.StringVar(&conf.jsurl, "jsurl", "", "URL to JavaScript file - cannot be used with url or file") + flag.StringVar(&conf.file, "file", "", "File containing URLs (one per line) - cannot be used with url or jsurl") flag.StringVar(&conf.proxy, "proxy", "", "Proxy URL") help := flag.Bool("help", false, "Show help") flag.BoolVar(&conf.insecure, "insecure", false, "Ignore invalid TLS certificates") flag.Var(&conf.headers, "header", "A header to send with the request, similar to curl's -H. Can be set multiple times, EG: \"./sourcemapper --header \"Cookie: session=bar\" --header \"Authorization: blerp\"") flag.Parse() - if *help || (conf.url == "" && conf.jsurl == "") || conf.outdir == "" { + if *help || (conf.url == "" && conf.jsurl == "" && conf.file == "") || conf.outdir == "" { flag.Usage() return } - if conf.jsurl != "" && conf.url != "" { - log.Println("[!] Both -jsurl and -url supplied") + // Check for mutually exclusive flags + flagCount := 0 + if conf.url != "" { + flagCount++ + } + if conf.jsurl != "" { + flagCount++ + } + if conf.file != "" { + flagCount++ + } + + if flagCount > 1 { + log.Println("[!] Only one of -url, -jsurl, or -file can be specified") flag.Usage() return } @@ -310,55 +390,62 @@ func main() { proxyURL = *p } - var sm sourceMap - - // these need to just take the conf object - if conf.url != "" { - if sm, err = getSourceMap(conf.url, conf.headers, conf.insecure, proxyURL); err != nil { - log.Fatal(err) + // Process URLs from file if -file flag is provided + if conf.file != "" { + urls, err := readURLsFromFile(conf.file) + if err != nil { + log.Fatalf("[!] Error reading file: %v", err) } - } else if conf.jsurl != "" { - if sm, err = getSourceMapFromJS(conf.jsurl, conf.headers, conf.insecure, proxyURL); err != nil { - log.Fatal(err) + + if len(urls) == 0 { + log.Fatal("[!] No URLs found in file") } - } - // everything below needs to go into its own function - log.Printf("[+] Retrieved Sourcemap with version %d, containing %d entries.\n", sm.Version, len(sm.Sources)) + log.Printf("[+] Processing %d URLs from file %s\n", len(urls), conf.file) - if len(sm.Sources) == 0 { - log.Fatal("No sources found.") - } + for idx, urlStr := range urls { + log.Printf("[+] Processing URL %d/%d: %s\n", idx+1, len(urls), urlStr) - if len(sm.SourcesContent) == 0 { - log.Fatal("No source content found.") - } + var sm sourceMap + // Determine if this is a JS URL or sourcemap URL + // For simplicity, we'll try to detect .js files and use getSourceMapFromJS + // otherwise use getSourceMap + if strings.HasSuffix(urlStr, ".js") { + sm, err = getSourceMapFromJS(urlStr, conf.headers, conf.insecure, proxyURL) + } else { + sm, err = getSourceMap(urlStr, conf.headers, conf.insecure, proxyURL) + } - if sm.Version != 3 { - log.Println("[!] Sourcemap is not version 3. This is untested!") - } + if err != nil { + log.Printf("[!] Error processing URL %s: %v\n", urlStr, err) + continue + } - if _, err := os.Stat(conf.outdir); os.IsNotExist(err) { - err = os.Mkdir(conf.outdir, 0700) - if err != nil { - log.Fatal(err) + if err := processSourceMap(sm, conf.outdir); err != nil { + log.Printf("[!] Error processing sourcemap for %s: %v\n", urlStr, err) + } } + + log.Println("[+] Done") + return } - for i, sourcePath := range sm.Sources { - sourcePath = "/" + sourcePath // path.Clean will ignore a leading '..', must be a '/..' - // If on windows, clean the sourcepath. - if runtime.GOOS == "windows" { - sourcePath = cleanWindows(sourcePath) - } + var sm sourceMap - // Use filepath.Join. https://parsiya.net/blog/2019-03-09-path.join-considered-harmful/ - scriptPath, scriptData := filepath.Join(conf.outdir, filepath.Clean(sourcePath)), sm.SourcesContent[i] - err := writeFile(scriptPath, scriptData) - if err != nil { - log.Printf("Error writing %s file: %s", scriptPath, err) + // Process single URL (original behavior) + if conf.url != "" { + if sm, err = getSourceMap(conf.url, conf.headers, conf.insecure, proxyURL); err != nil { + log.Fatal(err) + } + } else if conf.jsurl != "" { + if sm, err = getSourceMapFromJS(conf.jsurl, conf.headers, conf.insecure, proxyURL); err != nil { + log.Fatal(err) } } + if err := processSourceMap(sm, conf.outdir); err != nil { + log.Fatal(err) + } + log.Println("[+] Done") } From 3e31aaf151a2fa87a3b070433cb37ee90bab2f9a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:55:25 +0000 Subject: [PATCH 03/12] Add support for reading URLs from stdin with -stdin flag Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- main.go | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index f7e0126..41e199a 100755 --- a/main.go +++ b/main.go @@ -33,6 +33,7 @@ type config struct { url string // sourcemap url jsurl string // javascript url file string // file containing URLs + stdin bool // read URLs from stdin proxy string // upstream proxy server insecure bool // skip tls verification headers headerList // additional user-supplied http headers @@ -303,6 +304,25 @@ func readURLsFromFile(filepath string) ([]string, error) { return urls, nil } +// readURLsFromStdin reads URLs from stdin, one URL per line +func readURLsFromStdin() ([]string, error) { + var urls []string + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + // Skip empty lines and comments + if line != "" && !strings.HasPrefix(line, "#") { + urls = append(urls, line) + } + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return urls, nil +} + // processSourceMap processes a single sourcemap and writes its sources to disk func processSourceMap(sm sourceMap, outdir string) error { log.Printf("[+] Retrieved Sourcemap with version %d, containing %d entries.\n", sm.Version, len(sm.Sources)) @@ -350,16 +370,17 @@ func main() { var err error flag.StringVar(&conf.outdir, "output", "", "Source file output directory - REQUIRED") - flag.StringVar(&conf.url, "url", "", "URL or path to the Sourcemap file - cannot be used with jsurl or file") - flag.StringVar(&conf.jsurl, "jsurl", "", "URL to JavaScript file - cannot be used with url or file") - flag.StringVar(&conf.file, "file", "", "File containing URLs (one per line) - cannot be used with url or jsurl") + flag.StringVar(&conf.url, "url", "", "URL or path to the Sourcemap file - cannot be used with jsurl, file, or stdin") + flag.StringVar(&conf.jsurl, "jsurl", "", "URL to JavaScript file - cannot be used with url, file, or stdin") + flag.StringVar(&conf.file, "file", "", "File containing URLs (one per line) - cannot be used with url, jsurl, or stdin") + flag.BoolVar(&conf.stdin, "stdin", false, "Read URLs from stdin (one per line) - cannot be used with url, jsurl, or file") flag.StringVar(&conf.proxy, "proxy", "", "Proxy URL") help := flag.Bool("help", false, "Show help") flag.BoolVar(&conf.insecure, "insecure", false, "Ignore invalid TLS certificates") flag.Var(&conf.headers, "header", "A header to send with the request, similar to curl's -H. Can be set multiple times, EG: \"./sourcemapper --header \"Cookie: session=bar\" --header \"Authorization: blerp\"") flag.Parse() - if *help || (conf.url == "" && conf.jsurl == "" && conf.file == "") || conf.outdir == "" { + if *help || (conf.url == "" && conf.jsurl == "" && conf.file == "" && !conf.stdin) || conf.outdir == "" { flag.Usage() return } @@ -375,9 +396,12 @@ func main() { if conf.file != "" { flagCount++ } + if conf.stdin { + flagCount++ + } if flagCount > 1 { - log.Println("[!] Only one of -url, -jsurl, or -file can be specified") + log.Println("[!] Only one of -url, -jsurl, -file, or -stdin can be specified") flag.Usage() return } @@ -390,6 +414,46 @@ func main() { proxyURL = *p } + // Process URLs from stdin if -stdin flag is provided + if conf.stdin { + urls, err := readURLsFromStdin() + if err != nil { + log.Fatalf("[!] Error reading from stdin: %v", err) + } + + if len(urls) == 0 { + log.Fatal("[!] No URLs found in stdin") + } + + log.Printf("[+] Processing %d URLs from stdin\n", len(urls)) + + for idx, urlStr := range urls { + log.Printf("[+] Processing URL %d/%d: %s\n", idx+1, len(urls), urlStr) + + var sm sourceMap + // Determine if this is a JS URL or sourcemap URL + // For simplicity, we'll try to detect .js files and use getSourceMapFromJS + // otherwise use getSourceMap + if strings.HasSuffix(urlStr, ".js") { + sm, err = getSourceMapFromJS(urlStr, conf.headers, conf.insecure, proxyURL) + } else { + sm, err = getSourceMap(urlStr, conf.headers, conf.insecure, proxyURL) + } + + if err != nil { + log.Printf("[!] Error processing URL %s: %v\n", urlStr, err) + continue + } + + if err := processSourceMap(sm, conf.outdir); err != nil { + log.Printf("[!] Error processing sourcemap for %s: %v\n", urlStr, err) + } + } + + log.Println("[+] Done") + return + } + // Process URLs from file if -file flag is provided if conf.file != "" { urls, err := readURLsFromFile(conf.file) From b67307124c976497d2b2bd8d61ef3104c2292b95 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:57:26 +0000 Subject: [PATCH 04/12] Update README with documentation for -file and -stdin flags Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- README.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa22b75..1f9f1ed 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ pacman -S sourcemapper ```text :~$ ./sourcemapper Usage of ./sourcemapper: + -file string + File containing URLs (one per line) - cannot be used with url, jsurl, or stdin -header value A header to send with the request, similar to curl's -H. Can be set multiple times, EG: "./sourcemapper --header "Cookie: session=bar" --header "Authorization: blerp" -help @@ -39,13 +41,15 @@ Usage of ./sourcemapper: -insecure Ignore invalid TLS certificates -jsurl string - URL to JavaScript file - cannot be used with url + URL to JavaScript file - cannot be used with url, file, or stdin -output string Source file output directory - REQUIRED -proxy string Proxy URL + -stdin + Read URLs from stdin (one per line) - cannot be used with url, jsurl, or file -url string - URL or path to the Sourcemap file - cannot be used with jsurl + URL or path to the Sourcemap file - cannot be used with jsurl, file, or stdin ``` ## Extracting SourceMaps from .map URLs or local files @@ -102,3 +106,53 @@ $ ./sourcemapper -output test -jsurl http://localhost:8080/main.js ``` **Note: sourcemapper will retrieve any URL referenced as a sourcemap, so a malicious JavaScript file parsed with sourcemapper can force sourcemapper to make a GET request to any URL** + +## Processing Multiple URLs from a File + +The `-file` flag allows you to process multiple URLs at once by providing a file containing URLs (one per line). This is useful for batch processing multiple sourcemaps or JavaScript files. + +```text +$ cat urls.txt +# Lines starting with # are treated as comments +https://example.com/app.js +https://example.com/bundle.js.map +https://example.com/vendor.js + +$ ./sourcemapper -file urls.txt -output ./sources +[+] Processing 3 URLs from file urls.txt +[+] Processing URL 1/3: https://example.com/app.js +[+] Retrieving JavaScript from URL: https://example.com/app.js. +... +[+] Processing URL 2/3: https://example.com/bundle.js.map +[+] Retrieving Sourcemap from https://example.com/bundle.js.map... +... +[+] Done +``` + +Empty lines and lines starting with `#` are ignored, allowing you to add comments and organize your URL lists. + +## Reading URLs from stdin (httpx integration) + +The `-stdin` flag allows you to pipe URLs directly into sourcemapper, making it easy to integrate with tools like [httpx](https://github.com/projectdiscovery/httpx). This is particularly useful when you want to process URLs discovered by other tools. + +```text +$ cat urls.txt | ./sourcemapper -stdin -output ./sources +[+] Processing 3 URLs from stdin +[+] Processing URL 1/3: https://example.com/app.js +... +[+] Done +``` + +Example with httpx to discover and process JavaScript files: + +```text +$ cat domains.txt | httpx -mc 200 -path /app.js | ./sourcemapper -stdin -output ./sources +``` + +Or to find and process all .js.map files: + +```text +$ echo "https://example.com" | httpx -mc 200 -tech-detect | grep -i "\.js\.map" | ./sourcemapper -stdin -output ./sources +``` + +**Note: sourcemapper will retrieve any URL referenced as a sourcemap, so a malicious JavaScript file parsed with sourcemapper can force sourcemapper to make a GET request to any URL** From 8464a0a660c894cfa4a7f1e16f7fec629b4301de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:59:47 +0000 Subject: [PATCH 05/12] Refactor to reduce code duplication and improve URL type detection Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- main.go | 102 ++++++++++++++++++++++---------------------------------- 1 file changed, 40 insertions(+), 62 deletions(-) diff --git a/main.go b/main.go index 41e199a..68369f8 100755 --- a/main.go +++ b/main.go @@ -364,6 +364,44 @@ func processSourceMap(sm sourceMap, outdir string) error { return nil } +// getSourceMapFromURL retrieves a sourcemap from a URL, automatically detecting +// whether it's a JavaScript file or sourcemap based on the URL extension +func getSourceMapFromURL(urlStr string, headers []string, insecureTLS bool, proxyURL url.URL) (sourceMap, error) { + // Check for .js.map first (sourcemap), then .js (JavaScript) + if strings.HasSuffix(urlStr, ".js.map") || strings.HasSuffix(urlStr, ".map") { + return getSourceMap(urlStr, headers, insecureTLS, proxyURL) + } else if strings.HasSuffix(urlStr, ".js") { + return getSourceMapFromJS(urlStr, headers, insecureTLS, proxyURL) + } + // Default to treating as sourcemap for other extensions + return getSourceMap(urlStr, headers, insecureTLS, proxyURL) +} + +// processURLs processes multiple URLs from a list +func processURLs(urls []string, source string, outdir string, headers []string, insecureTLS bool, proxyURL url.URL) { + if len(urls) == 0 { + log.Fatalf("[!] No URLs found in %s", source) + } + + log.Printf("[+] Processing %d URLs from %s\n", len(urls), source) + + for idx, urlStr := range urls { + log.Printf("[+] Processing URL %d/%d: %s\n", idx+1, len(urls), urlStr) + + sm, err := getSourceMapFromURL(urlStr, headers, insecureTLS, proxyURL) + if err != nil { + log.Printf("[!] Error processing URL %s: %v\n", urlStr, err) + continue + } + + if err := processSourceMap(sm, outdir); err != nil { + log.Printf("[!] Error processing sourcemap for %s: %v\n", urlStr, err) + } + } + + log.Println("[+] Done") +} + func main() { var proxyURL url.URL var conf config @@ -420,37 +458,7 @@ func main() { if err != nil { log.Fatalf("[!] Error reading from stdin: %v", err) } - - if len(urls) == 0 { - log.Fatal("[!] No URLs found in stdin") - } - - log.Printf("[+] Processing %d URLs from stdin\n", len(urls)) - - for idx, urlStr := range urls { - log.Printf("[+] Processing URL %d/%d: %s\n", idx+1, len(urls), urlStr) - - var sm sourceMap - // Determine if this is a JS URL or sourcemap URL - // For simplicity, we'll try to detect .js files and use getSourceMapFromJS - // otherwise use getSourceMap - if strings.HasSuffix(urlStr, ".js") { - sm, err = getSourceMapFromJS(urlStr, conf.headers, conf.insecure, proxyURL) - } else { - sm, err = getSourceMap(urlStr, conf.headers, conf.insecure, proxyURL) - } - - if err != nil { - log.Printf("[!] Error processing URL %s: %v\n", urlStr, err) - continue - } - - if err := processSourceMap(sm, conf.outdir); err != nil { - log.Printf("[!] Error processing sourcemap for %s: %v\n", urlStr, err) - } - } - - log.Println("[+] Done") + processURLs(urls, "stdin", conf.outdir, conf.headers, conf.insecure, proxyURL) return } @@ -460,37 +468,7 @@ func main() { if err != nil { log.Fatalf("[!] Error reading file: %v", err) } - - if len(urls) == 0 { - log.Fatal("[!] No URLs found in file") - } - - log.Printf("[+] Processing %d URLs from file %s\n", len(urls), conf.file) - - for idx, urlStr := range urls { - log.Printf("[+] Processing URL %d/%d: %s\n", idx+1, len(urls), urlStr) - - var sm sourceMap - // Determine if this is a JS URL or sourcemap URL - // For simplicity, we'll try to detect .js files and use getSourceMapFromJS - // otherwise use getSourceMap - if strings.HasSuffix(urlStr, ".js") { - sm, err = getSourceMapFromJS(urlStr, conf.headers, conf.insecure, proxyURL) - } else { - sm, err = getSourceMap(urlStr, conf.headers, conf.insecure, proxyURL) - } - - if err != nil { - log.Printf("[!] Error processing URL %s: %v\n", urlStr, err) - continue - } - - if err := processSourceMap(sm, conf.outdir); err != nil { - log.Printf("[!] Error processing sourcemap for %s: %v\n", urlStr, err) - } - } - - log.Println("[+] Done") + processURLs(urls, "file "+conf.file, conf.outdir, conf.headers, conf.insecure, proxyURL) return } From b4a8e5a99f265f4d032c48bf103395a72e26f8d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:01:15 +0000 Subject: [PATCH 06/12] Improve URL type detection to handle query parameters and fragments Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- main.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 68369f8..a8d5656 100755 --- a/main.go +++ b/main.go @@ -367,10 +367,23 @@ func processSourceMap(sm sourceMap, outdir string) error { // getSourceMapFromURL retrieves a sourcemap from a URL, automatically detecting // whether it's a JavaScript file or sourcemap based on the URL extension func getSourceMapFromURL(urlStr string, headers []string, insecureTLS bool, proxyURL url.URL) (sourceMap, error) { - // Check for .js.map first (sourcemap), then .js (JavaScript) - if strings.HasSuffix(urlStr, ".js.map") || strings.HasSuffix(urlStr, ".map") { + // Parse the URL to extract the path without query parameters or fragments + parsedURL, err := url.Parse(urlStr) + if err != nil { + // If URL parsing fails, fall back to simple string matching + if strings.HasSuffix(urlStr, ".js.map") || strings.HasSuffix(urlStr, ".map") { + return getSourceMap(urlStr, headers, insecureTLS, proxyURL) + } else if strings.HasSuffix(urlStr, ".js") { + return getSourceMapFromJS(urlStr, headers, insecureTLS, proxyURL) + } + return getSourceMap(urlStr, headers, insecureTLS, proxyURL) + } + + // Check the path component for file extensions + path := parsedURL.Path + if strings.HasSuffix(path, ".js.map") || strings.HasSuffix(path, ".map") { return getSourceMap(urlStr, headers, insecureTLS, proxyURL) - } else if strings.HasSuffix(urlStr, ".js") { + } else if strings.HasSuffix(path, ".js") { return getSourceMapFromJS(urlStr, headers, insecureTLS, proxyURL) } // Default to treating as sourcemap for other extensions From bcff169ba6daec475a7c3bc0514554fdc0909352 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:51:51 +0000 Subject: [PATCH 07/12] Initial plan From 7e3b83aca7e5eee4cb9cbf7d12f3c2d4f299fd70 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:54:36 +0000 Subject: [PATCH 08/12] feat: add release workflow and update module path Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- .github/workflows/release.yml | 46 +++++++++++++++++++++++++++++++++++ README.md | 4 +-- go.mod | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..48e31b8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,46 @@ +name: Release + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - goos: linux + goarch: amd64 + - goos: darwin + goarch: amd64 + - goos: darwin + goarch: arm64 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - name: Build binary + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: 0 + run: | + go build -o sourcemapper + mv sourcemapper sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} + + - name: Upload release asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} + asset_name: sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} + asset_content_type: application/octet-stream diff --git a/README.md b/README.md index 1f9f1ed..3871400 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,13 @@ An article explaining its purpose is available here: [https://pulsesecurity.co.n If you have a recent version of Go installed: ```bash -go install github.com/denandz/sourcemapper@latest +go install github.com/IgorDuino/sourcemapper@latest ``` Otherwise you can clone and build: ```bash -git clone https://github.com/denandz/sourcemapper +git clone https://github.com/IgorDuino/sourcemapper cd sourcemapper go get go build diff --git a/go.mod b/go.mod index a224cca..0df48a5 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/denandz/sourcemapper +module github.com/IgorDuino/sourcemapper go 1.16 From ba5cf7bd62c4f28a66b66fa51078074329f732e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:55:22 +0000 Subject: [PATCH 09/12] chore: update release workflow tooling Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- .github/workflows/release.yml | 7 ++----- go.mod | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 48e31b8..2c4afe2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,11 +36,8 @@ jobs: mv sourcemapper sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} - name: Upload release asset - uses: actions/upload-release-asset@v1 + uses: softprops/action-gh-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ./sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} - asset_name: sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} - asset_content_type: application/octet-stream + files: sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} diff --git a/go.mod b/go.mod index 0df48a5..9e519a4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/IgorDuino/sourcemapper -go 1.16 +go 1.22 From d6dbb1786569f6162282ba60c1c7fda8863d0bed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:55:55 +0000 Subject: [PATCH 10/12] chore: harden release workflow Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- .github/workflows/release.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c4afe2..353a051 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,12 +32,14 @@ jobs: GOARCH: ${{ matrix.goarch }} CGO_ENABLED: 0 run: | - go build -o sourcemapper - mv sourcemapper sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} + ext="" + if [ "${{ matrix.goos }}" = "windows" ]; then ext=".exe"; fi + go build -o "sourcemapper${ext}" + mv "sourcemapper${ext}" "sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }}${ext}" - name: Upload release asset - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2.0.8 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - files: sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }} + files: sourcemapper-${{ matrix.goos }}-${{ matrix.goarch }}* From 6e7d656babb10363f08699d1d88c70f976ca6bfb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:56:34 +0000 Subject: [PATCH 11/12] chore: add windows target to release matrix Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 353a051..4c2efb0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,8 @@ jobs: goarch: amd64 - goos: darwin goarch: arm64 + - goos: windows + goarch: amd64 steps: - name: Checkout From dd9b48c15863ea5f00581ece17a002469f06a0ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Dec 2025 02:57:36 +0000 Subject: [PATCH 12/12] chore: set explicit workflow permissions Co-authored-by: IgorDuino <74809945+IgorDuino@users.noreply.github.com> --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c2efb0..e37f782 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,9 @@ on: release: types: [published] +permissions: + contents: write + jobs: build: runs-on: ubuntu-latest