fleet/pkg/open/open_windows.go
Scott Gress 634aa39746
Escape ampersands in URL when opening browser in windows (#35146)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #34847

# Details

In testing the new end-user auth flow for enrolling hosts on Windows, I
noticed that the `&host_uuid=<uuid>` part of the query string was
missing when opening the browser window, causing the SSO login process
to ultimately fail. I discovered that this is because the command we're
using to open the browser interprets `&` as a command separator, so it
needs to be escaped. This PR updated the `open` package for Windows, by
adding escaping to all `&` characters in a URL that are not already
escaped.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

## Testing

- [X] QA'd all new/changed functionality manually

Added a new tool for testing:

```
go run ./tools/open -url "http://google.com?x=y&owl=hoot^&foo=bar"
```

to test that it escapes ampersands correctly (and doesn't
double-escape).

## fleetd/orbit/Fleet Desktop

- [X] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [X] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
2025-11-04 09:20:31 -06:00

22 lines
573 B
Go

package open
import (
"os/exec"
"regexp"
"syscall"
)
var unescapedAmpsRegex = regexp.MustCompile(`([^\\^])&`)
func browser(url string) error {
// Replace all instances of & that are not already escaped with ^.
// This is necessary because cmd.exe treats & as a command separator.
url = unescapedAmpsRegex.ReplaceAllString(url, "${1}^&")
cmd := exec.Command("cmd", "/c", "start", url)
cmd.SysProcAttr = &syscall.SysProcAttr{
// HideWindow avoids a brief cmd console from opening
// before the browser opens the URL.
HideWindow: true,
}
return cmd.Run()
}