Skip to content

Commit aeee301

Browse files
committed
fix(security): prevent Windows command injection and improve RFC 7009 compliance
- Use rundll32 instead of cmd /c start to prevent shell metacharacter injection in URLs on Windows - Replace panic with fmt.Fprintf + os.Exit(1) for consistent error handling in loadConfig - Write token save warning to stderr instead of stdout in refreshAccessToken - Add token_type_hint parameter to revocation requests per RFC 7009
1 parent f358ea1 commit aeee301

4 files changed

Lines changed: 25 additions & 7 deletions

File tree

auth.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"net/http"
88
"net/url"
9+
"os"
910

1011
retry "github.com/appleboy/go-httpretry"
1112
"github.com/go-authgate/cli/tui"
@@ -94,7 +95,7 @@ func refreshAccessToken(
9495
}
9596

9697
if err := cfg.Store.Save(cfg.ClientID, *storage); err != nil {
97-
fmt.Printf("Warning: Failed to save refreshed tokens: %v\n", err)
98+
fmt.Fprintf(os.Stderr, "Warning: Failed to save refreshed tokens: %v\n", err)
9899
}
99100
return storage, nil
100101
}

browser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func openBrowser(ctx context.Context, url string) error {
1717
case "darwin":
1818
cmd = exec.CommandContext(ctx, "open", url)
1919
case "windows":
20-
cmd = exec.CommandContext(ctx, "cmd", "/c", "start", url)
20+
cmd = exec.CommandContext(ctx, "rundll32", "url.dll,FileProtocolHandler", url)
2121
default:
2222
cmd = exec.CommandContext(ctx, "xdg-open", url)
2323
}

config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ func loadConfig() *AppConfig {
236236
var err error
237237
cfg.RetryClient, err = retry.NewBackgroundClient(retry.WithHTTPClient(baseHTTPClient))
238238
if err != nil {
239-
panic(fmt.Sprintf("failed to create retry client: %v", err))
239+
fmt.Fprintf(os.Stderr, "Error: failed to create HTTP client: %v\n", err)
240+
os.Exit(1)
240241
}
241242

242243
// Resolve timeout configuration.

token_cmd.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,14 @@ func revokeTokenOnServer(
172172

173173
if tok.RefreshToken != "" {
174174
wg.Go(func() {
175-
if err := doRevoke(ctx, cfg, revokeURL, tok.RefreshToken, timeout); err != nil {
175+
if err := doRevoke(
176+
ctx,
177+
cfg,
178+
revokeURL,
179+
tok.RefreshToken,
180+
"refresh_token",
181+
timeout,
182+
); err != nil {
176183
mu.Lock()
177184
refreshErr = err
178185
mu.Unlock()
@@ -182,7 +189,14 @@ func revokeTokenOnServer(
182189

183190
if tok.AccessToken != "" {
184191
wg.Go(func() {
185-
if err := doRevoke(ctx, cfg, revokeURL, tok.AccessToken, timeout); err != nil {
192+
if err := doRevoke(
193+
ctx,
194+
cfg,
195+
revokeURL,
196+
tok.AccessToken,
197+
"access_token",
198+
timeout,
199+
); err != nil {
186200
mu.Lock()
187201
accessErr = err
188202
mu.Unlock()
@@ -213,14 +227,16 @@ func doRevoke(
213227
cfg *AppConfig,
214228
revokeURL string,
215229
token string,
230+
tokenTypeHint string,
216231
timeout time.Duration,
217232
) error {
218233
ctx, cancel := context.WithTimeout(ctx, timeout)
219234
defer cancel()
220235

221236
data := url.Values{
222-
"token": {token},
223-
"client_id": {cfg.ClientID},
237+
"token": {token},
238+
"token_type_hint": {tokenTypeHint},
239+
"client_id": {cfg.ClientID},
224240
}
225241
if !cfg.IsPublicClient() {
226242
data.Set("client_secret", cfg.ClientSecret)

0 commit comments

Comments
 (0)