@@ -59,61 +59,73 @@ 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+ "/run/current-system/sw/bin/gh" , // Nix
90+ "/nix/var/nix/profiles/default/bin/gh" , // Nix fallback
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+ "/usr/local/go/bin/gh" , // Go install
102+ filepath .Join (homeDir , "go" , "bin" , "gh" ), // Go install user
103+ "/opt/gh/bin/gh" , // Custom installs
104+ }
105+ default :
106+ // BSD and other Unix-like systems
107+ commonPaths = []string {
108+ "/usr/local/bin/gh" ,
109+ "/usr/bin/gh" ,
110+ "/usr/pkg/bin/gh" , // NetBSD pkgsrc
111+ "/opt/local/bin/gh" , // OpenBSD ports
112+ }
90113 }
91- }
92114
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- }
115+ for _ , path := range commonPaths {
116+ if path == "" {
117+ continue // Skip empty paths from unset env vars
118+ }
119+ if _ , err := os .Stat (path ); err == nil {
120+ log .Printf ("Found gh at common location: %s" , path )
121+ ghPath = path
122+ break
111123 }
112124 }
113125 }
114126
115127 if ghPath == "" {
116- return "" , errors .New ("gh cli not found in trusted locations and GITHUB_TOKEN not set" )
128+ return "" , errors .New ("gh CLI not found in PATH or common locations, and GITHUB_TOKEN not set" )
117129 }
118130
119131 log .Printf ("Executing command: %s auth token" , ghPath )
0 commit comments