app/cmd: restrict ollama:// URL scheme to supported paths (#13120)

This commit is contained in:
Eva H
2025-11-17 20:10:45 -05:00
committed by GitHub
parent 4aba2e8b72
commit 1fd4cb87b2
2 changed files with 13 additions and 20 deletions

View File

@@ -434,37 +434,30 @@ func openInBrowser(url string) {
} }
} }
// parseURLScheme parses an ollama:// URL and returns whether it's a connect URL and the UI path // parseURLScheme parses an ollama:// URL and validates it
func parseURLScheme(urlSchemeRequest string) (isConnect bool, uiPath string, err error) { // Supports: ollama:// (open app) and ollama://connect (OAuth)
func parseURLScheme(urlSchemeRequest string) (isConnect bool, err error) {
parsedURL, err := url.Parse(urlSchemeRequest) parsedURL, err := url.Parse(urlSchemeRequest)
if err != nil { if err != nil {
return false, "", err return false, fmt.Errorf("invalid URL: %w", err)
} }
// Check if this is a connect URL // Check if this is a connect URL
if parsedURL.Host == "connect" || strings.TrimPrefix(parsedURL.Path, "/") == "connect" { if parsedURL.Host == "connect" || strings.TrimPrefix(parsedURL.Path, "/") == "connect" {
return true, "", nil return true, nil
} }
// Extract the UI path // Allow bare ollama:// or ollama:/// to open the app
path := "/" if (parsedURL.Host == "" && parsedURL.Path == "") || parsedURL.Path == "/" {
if parsedURL.Path != "" && parsedURL.Path != "/" { return false, nil
// For URLs like ollama:///settings, use the path directly
path = parsedURL.Path
} else if parsedURL.Host != "" {
// For URLs like ollama://settings (without triple slash),
// the "settings" part is parsed as the host, not the path.
// We need to convert it to a path by prepending "/"
// This also handles ollama://settings/ where Windows adds a trailing slash
path = "/" + parsedURL.Host
} }
return false, path, nil return false, fmt.Errorf("unsupported ollama:// URL path: %s", urlSchemeRequest)
} }
// handleURLSchemeInCurrentInstance processes URL scheme requests in the current instance // handleURLSchemeInCurrentInstance processes URL scheme requests in the current instance
func handleURLSchemeInCurrentInstance(urlSchemeRequest string) { func handleURLSchemeInCurrentInstance(urlSchemeRequest string) {
isConnect, uiPath, err := parseURLScheme(urlSchemeRequest) isConnect, err := parseURLScheme(urlSchemeRequest)
if err != nil { if err != nil {
slog.Error("failed to parse URL scheme request", "url", urlSchemeRequest, "error", err) slog.Error("failed to parse URL scheme request", "url", urlSchemeRequest, "error", err)
return return
@@ -473,6 +466,6 @@ func handleURLSchemeInCurrentInstance(urlSchemeRequest string) {
if isConnect { if isConnect {
handleConnectURLScheme() handleConnectURLScheme()
} else { } else {
sendUIRequestMessage(uiPath) sendUIRequestMessage("/")
} }
} }

View File

@@ -138,7 +138,7 @@ func (app *appCallbacks) HandleURLScheme(urlScheme string) {
// handleURLSchemeRequest processes URL scheme requests from other instances // handleURLSchemeRequest processes URL scheme requests from other instances
func handleURLSchemeRequest(urlScheme string) { func handleURLSchemeRequest(urlScheme string) {
isConnect, uiPath, err := parseURLScheme(urlScheme) isConnect, err := parseURLScheme(urlScheme)
if err != nil { if err != nil {
slog.Error("failed to parse URL scheme request", "url", urlScheme, "error", err) slog.Error("failed to parse URL scheme request", "url", urlScheme, "error", err)
return return
@@ -147,7 +147,7 @@ func handleURLSchemeRequest(urlScheme string) {
if isConnect { if isConnect {
handleConnectURLScheme() handleConnectURLScheme()
} else { } else {
sendUIRequestMessage(uiPath) sendUIRequestMessage("/")
} }
} }