Repository: method-security/osintscan
Pull request #40: Update Docker Image with Rob Depedencies
Author: login: payoub125
Created: 2025-04-07T20:19:17Z | Merged: 2025-04-08T18:35:30Z

## Overview

- Emulating CI/CD for Webscan
- Added flag to point to path of headless browser

## Why Now?

- `Osintscan` was just updated to use Rod Headless Browser in the `SaaS Discovery` cmd
- Receiving an error when run stating dependencies where missing



Diff:
diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml
index 7a3fcc11..f8eb163e 100644
--- a/.github/workflows/reusable-build.yml
+++ b/.github/workflows/reusable-build.yml
@@ -13,15 +13,144 @@ on:
         type: string
 
 env:
-  GO_VERSION: "1.22"
+  GO_VERSION: "1.22.6"
 
 jobs:
+  prepare-linux:
+    name: Prepare Linux
+    runs-on: ubuntu-latest
+    env:
+      DOCKER_CLI_EXPERIMENTAL: "enabled"
+    steps:
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+
+      - name: Set up Docker Buildx
+        id: buildx
+        uses: docker/setup-buildx-action@v3
+
+      - name: Login to ghcr.io registry
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+
+      - name: Login to docker.io registry
+        uses: docker/login-action@v3
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+      - name: Checkout code
+        uses: actions/checkout@v4.1.6
+        with:
+          fetch-depth: 0
+
+      - name: Build ARM64 Builder Image
+        shell: bash
+        run: docker buildx build . --platform linux/arm64 --load --tag armbuilder -f Dockerfile.builder
+
+      - name: Build AMD64 Builder Image
+        shell: bash
+        run: docker buildx build . --platform linux/amd64 --load --tag amdbuilder -f Dockerfile.builder
+
+      - name: Build ARM64 Image
+        shell: bash
+        run: docker run -v .:/app/osintscan -e GOARCH=arm64 -e GOOS=linux -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} -e GORELEASER_KEY=${{ secrets.GORELEASER_KEY }} --rm armbuilder goreleaser build --single-target -f .goreleaser/goreleaser-build.yml ${{ inputs.goreleaser_options}}
+
+      - name: Build AMD64 Image
+        shell: bash
+        run: docker run -v .:/app/osintscan -e GOARCH=amd64 -e GOOS=linux -e GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} -e GORELEASER_KEY=${{ secrets.GORELEASER_KEY }} --rm amdbuilder goreleaser build --single-target -f .goreleaser/goreleaser-build.yml ${{ inputs.goreleaser_options}}
+
+      - uses: actions/upload-artifact@v4
+        with:
+          name: linux-dist
+          path: dist/
+          retention-days: 7
+
+  prepare:
+    name: Prepare
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [macos-latest, windows-latest]
+    runs-on: ${{ matrix.os }}
+    env:
+      DOCKER_CLI_EXPERIMENTAL: "enabled"
+      flags: ""
+    steps:
+      - name: Install Dependencies
+        run: |
+          brew update
+          brew install libpcap docker
+          echo "LD_LIBRARY_PATH=$(brew --prefix)/Cellar/libpcap/*/lib" >> $GITHUB_ENV
+        if: matrix.os == 'macos-latest'
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+        if: matrix.os == 'ubuntu-latest'
+
+      - name: Set up Docker Buildx
+        id: buildx
+        uses: docker/setup-buildx-action@v3
+        if: matrix.os == 'ubuntu-latest'
+
+      - name: Login to ghcr.io registry
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+        if: matrix.os != 'macos-latest'
+
+      - name: Checkout code
+        uses: actions/checkout@v4.1.6
+        with:
+          fetch-depth: 0
+
+      - name: Setup Go
+        uses: actions/setup-go@v5
+        with:
+          go-version: ${{ env.GO_VERSION }}
+          cache: false
+
+      - uses: goreleaser/goreleaser-action@v4
+        with:
+          distribution: goreleaser-pro
+          version: latest
+          args: build --single-target -f=.goreleaser/goreleaser-build.yml ${{ inputs.goreleaser_options }}
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
+
+      - uses: actions/upload-artifact@v4
+        with:
+          name: ${{ matrix.os }}-dist
+          path: dist/
+          retention-days: 7
+
   build:
     name: Build
+    needs:
+      - prepare
+      - prepare-linux
     runs-on: ubuntu-latest
     env:
       DOCKER_CLI_EXPERIMENTAL: "enabled"
     steps:
+      - name: Maximize build space
+        uses: easimon/maximize-build-space@v10
+        with:
+          root-reserve-mb: 32768 # The Go cache (`~/.cache/go-build` and `~/go/pkg`) requires a lot of storage space.
+          remove-android: "true"
+          remove-docker-images: "true"
+          remove-dotnet: "true"
+          remove-haskell: "true"
+
+      - name: Install Dependences
+        run: sudo apt install libpcap-dev
+
       - name: Set up QEMU
         uses: docker/setup-qemu-action@v3
 
@@ -29,6 +158,9 @@ jobs:
         id: buildx
         uses: docker/setup-buildx-action@v3
 
+      - name: Show available Docker Buildx platforms
+        run: echo ${{ steps.buildx.outputs.platforms }}
+
       - name: Install cosign
         uses: sigstore/cosign-installer@v3.5.0
 
@@ -57,18 +189,39 @@ jobs:
         uses: actions/setup-go@v5
         with:
           go-version: ${{ env.GO_VERSION }}
-          cache: false # Disable cache to avoid free space issues during `Post Setup Go` step.
+          cache: true
 
-      # Create tmp dir for GoReleaser
-      - name: "create tmp dir"
+      - name: Download Artifacts
+        uses: actions/download-artifact@v4
+        with:
+          path: artifacts
+
+      - name: View Artifacts
+        run: ls -al artifacts artifacts/*
+
+      - name: Arrange Artifacts
         run: |
-          mkdir tmp
+          mkdir -p output/build-linux_arm64/
+          mkdir -p output/build-linux_amd64/
+          mkdir -p output/build-darwin_arm64/
+          mkdir -p output/build-linux_amd64/
+          mkdir -p output/build-windows_amd64/
+          mv artifacts/linux-dist/linux_arm64/build-linux_linux_arm64/* output/build-linux_arm64/
+          mv artifacts/linux-dist/linux_amd64/build-linux_linux_amd64_v1/* output/build-linux_amd64/
+          mv artifacts/windows-latest-dist/windows_amd64/build-windows_windows_amd64_v1/* output/build-windows_amd64/
+          mv artifacts/macos-latest-dist/darwin_arm64/build-macos_darwin_arm64_v8.0/* output/build-darwin_arm64/
+        shell: bash
+
+      - name: View Output
+        run: ls -al output output/*
 
-      - name: GoReleaser
-        uses: goreleaser/goreleaser-action@v6
+      # release
+      - uses: goreleaser/goreleaser-action@v4
+        if: steps.cache.outputs.cache-hit != 'true'
         with:
-          version: v2.0.0
-          args: release -f=${{ inputs.goreleaser_config}} ${{ inputs.goreleaser_options}}
+          distribution: goreleaser-pro
+          version: latest
+          args: release -f=.goreleaser/goreleaser-publish.yml ${{ inputs.goreleaser_options}}
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          TMPDIR: "tmp"
+          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
diff --git a/.github/workflows/test-publish.yml b/.github/workflows/test-publish.yml
new file mode 100644
index 00000000..cd62c531
--- /dev/null
+++ b/.github/workflows/test-publish.yml
@@ -0,0 +1,22 @@
+name: 🔨 Publish Test
+on:
+  push:
+    branches:
+      - develop
+
+jobs:
+  test_fern_publish:
+    name: Test Fern Python Publish
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v3
+      - name: Setup Node
+        uses: actions/setup-node@v4
+      - name: Install Fern
+        run: npm install -g fern-api
+      - name: Generate Fern
+        run: fern generate --group pypi-test
+        env:
+          FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+          TEST_PYPI_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }}
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml
index 63eceab3..2d18d066 100644
--- a/.github/workflows/verify.yml
+++ b/.github/workflows/verify.yml
@@ -18,7 +18,7 @@ jobs:
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
-        
+
       - name: Setup Go
         uses: actions/setup-go@v5
         with:
diff --git a/.gitignore b/.gitignore
index ebc2826f..940e40a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,4 +38,7 @@ generated/python/**
 /site
 
 # Don't ignore vendors
-!vendor/**
\ No newline at end of file
+!vendor/**
+
+# Repo Binary
+osintscan
diff --git a/.goreleaser/goreleaser-build.yml b/.goreleaser/goreleaser-build.yml
new file mode 100644
index 00000000..687efe7b
--- /dev/null
+++ b/.goreleaser/goreleaser-build.yml
@@ -0,0 +1,53 @@
+# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
+# vim: set ts=2 sw=2 tw=0 fo=cnqoj
+
+version: 2
+
+project_name: osintscan
+
+partial:
+  by: target
+
+builds:
+  - id: build-linux
+    main: .
+    binary: osintscan
+    ldflags:
+      - -s -w
+      - "-extldflags '-static -lm -ldl -lpthread'"
+      - -X github.com/method-security/osintscan/main.version={{.Version}}
+    env:
+      - CGO_ENABLED=0
+    goos:
+      - linux
+    goarch:
+      - arm64
+      - amd64
+    goarm:
+      - "7"
+  - id: build-macos
+    main: .
+    binary: osintscan
+    ldflags:
+      - -s -w
+      - -X github.com/method-security/osintscan/main.version={{.Version}}
+    env:
+      - CGO_ENABLED=1
+    goos:
+      - darwin
+    goarch:
+      - arm64
+    goarm:
+      - "7"
+  - id: build-windows
+    main: .
+    binary: osintscan
+    ldflags:
+      - -s -w
+      - -X github.com/method-security/osintscan/main.version={{.Version}}
+    env:
+      - CGO_ENABLED=1
+    goos:
+      - windows
+    goarch:
+      - amd64
diff --git a/goreleaser.yml b/.goreleaser/goreleaser-publish.yml
similarity index 82%
rename from goreleaser.yml
rename to .goreleaser/goreleaser-publish.yml
index 66ce0da2..8d0bb184 100644
--- a/goreleaser.yml
+++ b/.goreleaser/goreleaser-publish.yml
@@ -1,56 +1,27 @@
 version: 2
 
 project_name: osintscan
+
 builds:
-  - id: build-linux
-    main: .
-    binary: osintscan
-    ldflags:
-      - -s -w
-      - "-extldflags '-static'"
-      - -X github.com/method-security/osintscan/main.version={{.Version}}
-    env:
-      - CGO_ENABLED=0
+  - id: prebuilt
+    builder: prebuilt
     goos:
       - linux
-    goarch:
-      - "386"
-      - arm
-      - amd64
-      - arm64
-    goarm:
-      - "7"
-  - id: build-macos
-    main: .
-    binary: osintscan
-    ldflags:
-      - -s -w
-      - "-extldflags '-static'"
-      - -X github.com/method-security/osintscan/main.version={{.Version}}
-    env:
-      - CGO_ENABLED=0
-    goos:
       - darwin
+      - windows
     goarch:
       - amd64
       - arm64
-    goarm:
-      - "7"
-  - id: build-windows
-    main: .
+    goamd64:
+      - v1
+    ignore:
+      - goos: windows
+        goarch: arm64
+      - goos: darwin
+        goarch: amd64
+    prebuilt:
+      path: output/build-{{ .Os }}_{{ .Arch }}/osintscan{{ if eq .Os "windows" }}.exe{{ end }}
     binary: osintscan
-    ldflags:
-      - -s -w
-      - "-extldflags '-static'"
-      - -X github.com/method-security/osintscan/main.version={{.Version}}
-    env:
-      - CGO_ENABLED=0
-    goos:
-      - windows
-    goarch:
-      - amd64
-    goarm:
-      - "7"
 
 archives:
   - id: archive
@@ -72,6 +43,9 @@ archives:
       - goos: windows
         format: zip
 
+checksum:
+  name_template: "{{ .ProjectName }}_checksums.txt"
+
 dockers:
   - image_templates:
       - "ghcr.io/method-security/osintscan:{{ .Version }}-amd64"
@@ -82,10 +56,10 @@ dockers:
     goos: linux
     goarch: amd64
     ids:
-      - build-linux
+      - prebuilt
     build_flag_templates:
       - "--label=org.opencontainers.image.title={{ .ProjectName }}"
-      - "--label=org.opencontainers.image.description=An on-rails OSINT enumeration tool"
+      - "--label=org.opencontainers.image.description=An on-rails AWS enumeration tool"
       - "--label=org.opencontainers.image.vendor=Method Security"
       - "--label=org.opencontainers.image.version={{ .Version }}"
       - "--label=org.opencontainers.image.created={{ .Date }}"
@@ -105,10 +79,10 @@ dockers:
     goos: linux
     goarch: arm64
     ids:
-      - build-linux
+      - prebuilt
     build_flag_templates:
       - "--label=org.opencontainers.image.title={{ .ProjectName }}"
-      - "--label=org.opencontainers.image.description=An on-rails OSINT enumeration tool"
+      - "--label=org.opencontainers.image.description=An on-rails AWS enumeration tool"
       - "--label=org.opencontainers.image.vendor=Method Security"
       - "--label=org.opencontainers.image.version={{ .Version }}"
       - "--label=org.opencontainers.image.created={{ .Date }}"
@@ -119,7 +93,6 @@ dockers:
       - "--platform=linux/arm64"
     extra_files:
       - configs/
-
 docker_manifests:
   - name_template: 'ghcr.io/method-security/osintscan:{{ .Version }}'
     image_templates:
@@ -138,17 +111,6 @@ docker_manifests:
     - 'methodsecurity/osintscan:{{ .Version }}-amd64'
     - 'methodsecurity/osintscan:{{ .Version }}-arm64'
 
-source:
-  enabled: true
-
-checksum:
-  name_template: "{{ .ProjectName }}_checksums.txt"
-
-sboms:
-  - artifacts: archive
-  - id: source
-    artifacts: source
-
 signs:
   - cmd: cosign
     env:
@@ -175,3 +137,8 @@ docker_signs:
     - "sign"
     - "${artifact}"
     - "--yes"
+
+sboms:
+  - artifacts: archive
+  - id: source
+    artifacts: source
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 409d2a1d..a7df52c1 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,7 @@
 FROM chromedp/headless-shell:129.0.6643.2 
 
 ARG CLI_NAME="osintscan"
+ARG TARGETARCH
 
 RUN apt-get update && apt-get install -y ca-certificates git
 
@@ -17,7 +18,7 @@ RUN \
   mkdir -p /opt/method/${CLI_NAME}/var/log && \
   mkdir -p /opt/method/${CLI_NAME}/service/bin && \
   mkdir -p /mnt/output
-
+  
 COPY configs/dns/subenum/*                   /opt/method/${CLI_NAME}/var/conf/dns/subenum/
 COPY configs/dns/takeover/*                  /opt/method/${CLI_NAME}/var/conf/dns/takeover/
 COPY configs/saas/*                          /opt/method/${CLI_NAME}/var/conf/saas/
@@ -33,4 +34,5 @@ USER method
 WORKDIR /opt/method/${CLI_NAME}/
 
 ENV PATH="/opt/method/${CLI_NAME}/service/bin:${PATH}"
+
 ENTRYPOINT [ "osintscan" ]
diff --git a/Dockerfile.builder b/Dockerfile.builder
new file mode 100644
index 00000000..e3941474
--- /dev/null
+++ b/Dockerfile.builder
@@ -0,0 +1,30 @@
+# Dockerfile used for the compilation of the statically compiled osintscan binary
+FROM golang:1.22.6-alpine3.20 AS base
+ARG GORELEASER_VERSION="v2.0.1"
+ARG CLI_NAME="osintscan"
+ARG TARGETARCH
+
+RUN \
+  apk add --no-cache git gcc musl-dev bash && \
+  mkdir -p /app/${CLI_NAME} && \
+  git config --global --add safe.directory /app/${CLI_NAME}
+
+WORKDIR /app/${CLI_NAME}
+
+FROM base AS amd64
+ARG CLI_NAME
+ARG GORELEASER_VERSION
+RUN \
+  wget https://github.com/goreleaser/goreleaser-pro/releases/download/${GORELEASER_VERSION}-pro/goreleaser-pro_Linux_x86_64.tar.gz && \
+  tar -xvzf goreleaser-pro_Linux_x86_64.tar.gz && \
+  mv goreleaser /usr/local/bin/goreleaser && \
+  rm -rf goreleaser-pro_Linux_x86_64.tar.gz LICENSE.md README.md completions manpages
+
+FROM base AS arm64
+ARG CLI_NAME
+RUN \
+  wget https://github.com/goreleaser/goreleaser-pro/releases/download/${GORELEASER_VERSION}-pro/goreleaser-pro_Linux_arm64.tar.gz && \
+  tar -xvzf goreleaser-pro_Linux_arm64.tar.gz && \
+  mv goreleaser /usr/local/bin/goreleaser && \
+  rm -rf goreleaser-pro_Linux_arm64.tar.gz LICENSE.md README.md completions manpages
+
diff --git a/README.md b/README.md
index a846031a..88b42292 100644
--- a/README.md
+++ b/README.md
@@ -36,6 +36,25 @@ osintscan dns records --domain example.com
 
 ```bash
 osintscan dns certs --domain example.com
+
+### Building a Statically Compiled Container for Local Testing
+(Reference reusable-build.yaml)
+
+1. Build ARM64 builder image: `docker buildx build . --platform linux/arm64 --load --tag armbuilder -f Dockerfile.builder`
+
+2. Build ARM64 image: `docker run -v .:/app/osintscan -e GOARCH=arm64 -e GOOS=linux --rm armbuilder goreleaser build --single-target -f .goreleaser/goreleaser-build.yml --snapshot --clean`
+
+3. `cp dist/linux_arm64/build-linux_linux_arm64/osintscan .`
+
+4. `docker buildx build . --platform linux/arm64 --load --tag osintscan:local -f Dockerfile`
+
+5. Open shell: `docker run -it --rm --entrypoint /bin/bash osintscan:local`
+
+6. OR run command without shell example: `docker run osintscan:local discovery saas --org example -o json`
+
+
+### Note:
+This tool runs on a headless-shell base image to support chrome/chromium browser automation. The dockerfile uses debian-based install tools. 
 ```
 
 ## Contributing
diff --git a/cmd/saas.go b/cmd/saas.go
index 4c8ad599..6a11e39b 100644
--- a/cmd/saas.go
+++ b/cmd/saas.go
@@ -82,8 +82,13 @@ func (a *OsintScan) InitSaasCommand() {
 				a.OutputSignal.AddError(err)
 				return
 			}
+			browserPath, err := cmd.Flags().GetString("browserpath")
+			if err != nil {
+				a.OutputSignal.AddError(err)
+				return
+			}
 
-			config := saasDiscoveryConfig(orgs, saasFilePaths, ssoFilePaths, saasCompanies, ssoCompanies, timeout, httpsOnly, successfulOnly, skipTLS)
+			config := saasDiscoveryConfig(orgs, saasFilePaths, ssoFilePaths, saasCompanies, ssoCompanies, timeout, httpsOnly, successfulOnly, skipTLS, browserPath)
 
 			// Generate the report
 			report, err := saasdiscovery.Discovery(cmd.Context(), saasFingerprints, ssoFingerprints, config)
@@ -104,6 +109,7 @@ func (a *OsintScan) InitSaasCommand() {
 	discoveryCmd.Flags().Bool("httpsonly", true, "Only use HTTPS for the requests")
 	discoveryCmd.Flags().Bool("successfulonly", false, "Only return results where the finding is a success")
 	discoveryCmd.Flags().Bool("skiptls", false, "Skip TLS verification")
+	discoveryCmd.Flags().String("browserpath", "", "The path to the browser to use for the requests")
 
 	_ = discoveryCmd.MarkFlagRequired("orgs")
 
@@ -111,7 +117,7 @@ func (a *OsintScan) InitSaasCommand() {
 	a.RootCmd.AddCommand(a.SaasCmd)
 }
 
-func saasDiscoveryConfig(orgs []string, saasFilePaths []string, ssoFilePaths []string, saasCompanies []string, ssoCompanies []string, timeout int, httpsOnly bool, successfulOnly bool, skipTLS bool) saasFern.SaasDiscoveryConfig {
+func saasDiscoveryConfig(orgs []string, saasFilePaths []string, ssoFilePaths []string, saasCompanies []string, ssoCompanies []string, timeout int, httpsOnly bool, successfulOnly bool, skipTLS bool, browserPath string) saasFern.SaasDiscoveryConfig {
 	config := saasFern.SaasDiscoveryConfig{
 		Orgs:           orgs,
 		SaasFilePaths:  saasFilePaths,
@@ -121,6 +127,9 @@ func saasDiscoveryConfig(orgs []string, saasFilePaths []string, ssoFilePaths []s
 		SuccessfulOnly: successfulOnly,
 		SkipTls:        skipTLS,
 	}
+	if len(browserPath) > 0 {
+		config.BrowserPath = &browserPath
+	}
 	if len(saasCompanies) > 0 {
 		config.SaasCompanies = saasCompanies
 	}
diff --git a/fern/definition/saas/saasdiscovery.yml b/fern/definition/saas/saasdiscovery.yml
index 0793ee5e..2abfc90d 100644
--- a/fern/definition/saas/saasdiscovery.yml
+++ b/fern/definition/saas/saasdiscovery.yml
@@ -24,6 +24,7 @@ types:
       httpsOnly: boolean
       successfulOnly: boolean
       skipTLS: boolean
+      browserPath: optional<string>
   # Report
   SaaSDiscoveryFinding:
     properties:
diff --git a/generated/go/saas/types.go b/generated/go/saas/types.go
index 74278d07..4f5fdaa3 100644
--- a/generated/go/saas/types.go
+++ b/generated/go/saas/types.go
@@ -144,6 +144,7 @@ type SaasDiscoveryConfig struct {
 	HttpsOnly      bool     `json:"httpsOnly" url:"httpsOnly"`
 	SuccessfulOnly bool     `json:"successfulOnly" url:"successfulOnly"`
 	SkipTls        bool     `json:"skipTLS" url:"skipTLS"`
+	BrowserPath    *string  `json:"browserPath,omitempty" url:"browserPath,omitempty"`
 
 	extraProperties map[string]interface{}
 	_rawJSON        json.RawMessage
diff --git a/internal/saas/discovery/discovery.go b/internal/saas/discovery/discovery.go
index 656aae01..830e125c 100644
--- a/internal/saas/discovery/discovery.go
+++ b/internal/saas/discovery/discovery.go
@@ -92,7 +92,7 @@ func handleSaasRequest(
 	fingerprint *saasFern.SaasFingerprintEntry,
 	selectedSsoFingerprints saasFern.SaasFingerprintFile,
 ) (*saasFern.SaasDiscoveryRequest, []string) {
-	request, errs := sendSaasRequest(ctx, org, domainSlug, schema, config.Timeout, config.SkipTls)
+	request, errs := sendSaasRequest(ctx, org, domainSlug, schema, config.Timeout, config.BrowserPath, config.SkipTls)
 
 	// Check if the page was redirected
 	redirectedPage := false
@@ -106,7 +106,7 @@ func handleSaasRequest(
 	return request, errs
 }
 
-func sendSaasRequest(ctx context.Context, org string, domainSlug string, schema string, timeout int, skipTLS bool) (*saasFern.SaasDiscoveryRequest, []string) {
+func sendSaasRequest(ctx context.Context, org string, domainSlug string, schema string, timeout int, browserPath *string, skipTLS bool) (*saasFern.SaasDiscoveryRequest, []string) {
 	// Initialize variables
 	var redirectChain []string
 	var errors []string
@@ -118,7 +118,12 @@ func sendSaasRequest(ctx context.Context, org string, domainSlug string, schema
 	log.Printf("Sending request to %s", fullURL)
 
 	// Setup browser launch options
-	launch := launcher.New()
+	var launch *launcher.Launcher
+	if browserPath != nil && *browserPath != "" {
+		launch = launcher.New().Headless(true).Bin(*browserPath)
+	} else {
+		launch = launcher.New().Headless(true)
+	}
 	if skipTLS {
 		launch.Set("ignore-certificate-errors")
 	}


Reviews:
user: login: sean-hacker
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T20:19:53Z
user: login: sean-hacker
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T18:13:11Z
user: login: sean-hacker
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T18:35:13Z

Review comments:
path: osintscan
user: login: sean-hacker
body: Don't check this in. Also should add to gitignore
created_at: 2025-04-07T20:19:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,30 @@
+# Dockerfile used for the compilation of the statically compiled osintscan binary
+FROM golang:1.22.4-alpine3.20 AS base
path: Dockerfile.builder
user: login: sean-hacker
body: You use 1.22.6 in your go.mod
created_at: 2025-04-08T18:13:11Z
author_association: CONTRIBUTOR

PR comments:
user: login: sean-hacker
created_at: 2025-04-07T20:20:30Z
body: @payoub125 , why do we need these? I don't remember doing this in webscan but could be misremembering
author_association: CONTRIBUTOR
user: login: payoub125
created_at: 2025-04-07T20:23:55Z
body: > @payoub125 , why do we need these? I don't remember doing this in webscan but could be misremembering

@sean-hacker You are correct, we dont do them in Webscan. I kept hitting dependency errors when I built the Dockerfile and ran it locally. I wanted to get it working and then run the git pipeline (out of curiousity) and then I was going to dig in and see why webscan is different
author_association: CONTRIBUTOR
user: login: payoub125
created_at: 2025-04-07T20:46:24Z
body: > o

Here is were it is done in webscan

```
    steps:
      - name: Install Dependencies
        run: |
          brew update
          brew install libpcap docker
          echo "LD_LIBRARY_PATH=$(brew --prefix)/Cellar/libpcap/*/lib" >> $GITHUB_ENV
        if: matrix.os == 'macos-latest'
```
author_association: CONTRIBUTOR
user: login: sean-hacker
created_at: 2025-04-07T20:59:06Z
body: If you're running locally that would explain the mac pipeline. It would seem like libpcap installed the rest automatically. I admittedly have not tried to build webscan locally.
author_association: CONTRIBUTOR