{"record":{"id":"b35da9d159923c53","repo":"git-ecosystem/git-credential-manager","slug":"can-only-open-http-https-uris","errorCode":null,"errorMessage":"Can only open HTTP/HTTPS URIs","messagePattern":"Can only open HTTP/HTTPS URIs","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Core/ISessionManager.cs","lineNumber":67,"sourceCode":"            EnsureArgument.NotNull(trace, nameof(trace));\n            EnsureArgument.NotNull(env, nameof(env));\n            EnsureArgument.NotNull(fs, nameof(fs));\n\n            Trace = trace;\n            Environment = env;\n            FileSystem = fs;\n        }\n        \n        public abstract bool IsDesktopSession { get; }\n\n        public virtual bool IsWebBrowserAvailable => IsDesktopSession;\n\n        public void OpenBrowser(Uri uri)\n        {\n            if (!uri.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) &&\n                !uri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))\n            {\n                throw new ArgumentException(\"Can only open HTTP/HTTPS URIs\", nameof(uri));\n            }\n\n            // Important! Use AbsoluteUri to ensure that the URL is properly\n            // escaped (e.g. spaces are converted to %20).\n            // The 'shell execute' handler on some operating systems (e.g. macOS)\n            // will try to validate the URL handed to it and if it sees any\n            // unescaped characters it will decide that the rest of the query\n            // parameters also need esacaping leading to double escaping!\n            OpenBrowserInternal(uri.AbsoluteUri);\n        }\n\n        protected virtual void OpenBrowserInternal(string url)\n        {\n            Trace.WriteLine(\"Opening browser using framework shell-execute: \" + url);\n            var psi = new ProcessStartInfo(url) { UseShellExecute = true };\n            Process.Start(psi);\n        }\n    }","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/ISessionManager.cs#L49-L85","documentation":"SessionManager.OpenBrowser(Uri) only permits http and https schemes because the URL is passed to a shell-execute handler; other schemes (file:, ftp:, javascript:) are rejected with an ArgumentException. This is a security measure to prevent launching arbitrary handlers via crafted URIs.","triggerScenarios":"Calling OpenBrowser with an absolute Uri whose Scheme is not http/https — e.g. file://, ftp://, ssh://, or a custom scheme.","commonSituations":"Redirect responses returning a non-HTTP URL, tests or tools passing local file:// links for a device-login page, or malicious/typoed redirect URLs from an identity provider.","solutions":["Use the https:// (or http://) form of the URL before opening it in the browser","Check uri.Scheme before calling OpenBrowser and show a user-facing error for non-HTTP URLs","If a file needs to be shown, serve it over a local HTTP server instead of a file:// URI","Investigate why a non-HTTP URL was produced (redirect chain, config value) and fix the source"],"exampleFix":"// before\nsm.OpenBrowser(new Uri(\"file:///tmp/login.html\")); // throws\n// after\nvar uri = new Uri(\"https://github.com/login/device\");\nif (uri.Scheme == Uri.UriSchemeHttps)\n    sm.OpenBrowser(uri);","handlingStrategy":"validation","validationCode":"if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)\n    throw new ArgumentException($\"Refusing to open non-HTTP URI in browser: {uri}\");","typeGuard":"bool IsHttpUri(Uri u) => u.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||\n    u.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try\n{\n    sm.OpenBrowser(uri);\n}\ncatch (ArgumentException ex) when (ex.Message == \"Can only open HTTP/HTTPS URIs\")\n{\n    logger.LogError(ex, \"Unexpected URI scheme {Scheme} from auth flow\", uri.Scheme);\n}","preventionTips":["Sanitize redirect/auth URLs received from servers before opening them","Treat non-HTTP URLs in auth flows as suspicious and surface an error instead of launching","Convert file-based content to a local http:// endpoint if it must be shown in a browser"],"tags":["uri","browser","scheme-validation","security"],"backgroundTag":"invalid-url-format","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}