@@ -59,61 +59,75 @@ func (*App) token(ctx context.Context) (string, error) {
5959 log .Println ("Using GitHub token from GITHUB_TOKEN environment variable" )
6060 return token , nil
6161 }
62- // Only check absolute paths for security - never use PATH
63- var trustedPaths []string
64- switch runtime .GOOS {
65- case "windows" :
66- trustedPaths = []string {
67- `C:\Program Files\GitHub CLI\gh.exe` ,
68- `C:\Program Files (x86)\GitHub CLI\gh.exe` ,
69- filepath .Join (os .Getenv ("LOCALAPPDATA" ), "Programs" , "gh" , "gh.exe" ),
70- filepath .Join (os .Getenv ("LOCALAPPDATA" ), "GitHub CLI" , "gh.exe" ),
62+ // Try to find gh in PATH first
63+ ghPath , err := exec .LookPath ("gh" )
64+ if err == nil {
65+ log .Printf ("Found gh in PATH at: %s" , ghPath )
66+ // Resolve any symlinks to get the real path
67+ if realPath , err := filepath .EvalSymlinks (ghPath ); err == nil {
68+ ghPath = realPath
69+ log .Printf ("Resolved to: %s" , ghPath )
7170 }
72- case "darwin" :
73- trustedPaths = []string {
74- "/opt/homebrew/bin/gh" , // Homebrew on Apple Silicon
75- "/usr/local/bin/gh" , // Homebrew on Intel / manual install
76- "/usr/bin/gh" , // System package managers
77- }
78- case "linux" :
79- trustedPaths = []string {
80- "/usr/local/bin/gh" , // Manual install
81- "/usr/bin/gh" , // System package managers
82- "/home/linuxbrew/.linuxbrew/bin/gh" , // Linuxbrew
83- "/snap/bin/gh" , // Snap package
84- }
85- default :
86- // BSD and other Unix-like systems
87- trustedPaths = []string {
88- "/usr/local/bin/gh" ,
89- "/usr/bin/gh" ,
71+ } else {
72+ // Fall back to checking common installation paths
73+ log .Print ("gh not found in PATH, checking common locations..." )
74+ var commonPaths []string
75+ switch runtime .GOOS {
76+ case "windows" :
77+ commonPaths = []string {
78+ `C:\Program Files\GitHub CLI\gh.exe` ,
79+ `C:\Program Files (x86)\GitHub CLI\gh.exe` ,
80+ filepath .Join (os .Getenv ("LOCALAPPDATA" ), "Programs" , "gh" , "gh.exe" ),
81+ filepath .Join (os .Getenv ("LOCALAPPDATA" ), "GitHub CLI" , "gh.exe" ),
82+ }
83+ case "darwin" :
84+ commonPaths = []string {
85+ "/opt/homebrew/bin/gh" , // Homebrew on Apple Silicon
86+ "/usr/local/bin/gh" , // Homebrew on Intel / manual install
87+ "/usr/bin/gh" , // System package managers
88+ "/opt/local/bin/gh" , // MacPorts
89+ "/sw/bin/gh" , // Fink
90+ "/nix/var/nix/profiles/default/bin/gh" , // Nix
91+ }
92+ case "linux" :
93+ homeDir := os .Getenv ("HOME" )
94+ commonPaths = []string {
95+ "/usr/local/bin/gh" , // Manual install
96+ "/usr/bin/gh" , // System package managers (apt, dnf, etc)
97+ "/home/linuxbrew/.linuxbrew/bin/gh" , // Linuxbrew
98+ "/snap/bin/gh" , // Snap package
99+ "/run/current-system/sw/bin/gh" , // NixOS
100+ "/var/lib/flatpak/exports/bin/gh" , // Flatpak system
101+ filepath .Join (homeDir , ".local" , "share" , "flatpak" , "exports" , "bin" , "gh" ), // Flatpak user
102+ "/usr/local/go/bin/gh" , // Go install
103+ filepath .Join (homeDir , "go" , "bin" , "gh" ), // Go install user
104+ filepath .Join (homeDir , ".local" , "bin" , "gh" ), // pip/pipx install
105+ "/opt/gh/bin/gh" , // Custom installs
106+ }
107+ default :
108+ // BSD and other Unix-like systems
109+ commonPaths = []string {
110+ "/usr/local/bin/gh" ,
111+ "/usr/bin/gh" ,
112+ "/usr/pkg/bin/gh" , // NetBSD pkgsrc
113+ "/opt/local/bin/gh" , // OpenBSD ports
114+ }
90115 }
91- }
92116
93- var ghPath string
94- for _ , path := range trustedPaths {
95- // Verify the file exists and is executable
96- if info , err := os .Stat (path ); err == nil {
97- // Check if it's a regular file and executable
98- const executableMask = 0o111
99- if info .Mode ().IsRegular () && info .Mode ()& executableMask != 0 {
100- // Verify it's actually the gh binary by running version command
101- // Use timeout to prevent hanging
102- versionCtx , cancel := context .WithTimeout (ctx , 2 * time .Second )
103- cmd := exec .CommandContext (versionCtx , path , "version" )
104- output , err := cmd .Output ()
105- cancel () // Call cancel immediately after command execution
106- if err == nil && strings .Contains (string (output ), "gh version" ) {
107- log .Printf ("Found and verified gh at: %s" , path )
108- ghPath = path
109- break
110- }
117+ for _ , path := range commonPaths {
118+ if path == "" {
119+ continue // Skip empty paths from unset env vars
120+ }
121+ if _ , err := os .Stat (path ); err == nil {
122+ log .Printf ("Found gh at common location: %s" , path )
123+ ghPath = path
124+ break
111125 }
112126 }
113127 }
114128
115129 if ghPath == "" {
116- return "" , errors .New ("gh cli not found in trusted locations and GITHUB_TOKEN not set" )
130+ return "" , errors .New ("gh CLI not found in PATH or common locations, and GITHUB_TOKEN not set" )
117131 }
118132
119133 log .Printf ("Executing command: %s auth token" , ghPath )
0 commit comments