{"record":{"id":"5102fa6258f7e0c7","repo":"argoproj/argo-workflows","slug":"logout-redirect-url-must-be-an-absolute-http-s-ur","errorCode":null,"errorMessage":"logout redirect URL must be an absolute HTTP(S) URL without user info or a fragment: %q","messagePattern":"logout redirect URL must be an absolute HTTP\\(S\\) URL without user info or a fragment: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/logout/logout.go","lineNumber":40,"sourceCode":"// If the provider end-session URL is invalid, the handler falls back to the local redirect and returns the validation error.\nfunc NewHandler(baseHRef, redirectURL string, secure bool, logoutURL, clientID string) (*Handler, error) {\n\tbaseHRef = authcookie.NormalizePath(baseHRef)\n\tcookiePaths := []string{baseHRef}\n\tif legacyCookiePath := strings.TrimSuffix(baseHRef, \"/\"); legacyCookiePath != \"\" {\n\t\tcookiePaths = append(cookiePaths, legacyCookiePath)\n\t}\n\tif redirectURL == \"\" {\n\t\tredirectURL = baseHRef\n\t\tlogoutURL = \"\"\n\t}\n\tfinalRedirectURL, err := constructLogoutURL(logoutURL, clientID, redirectURL)\n\treturn &Handler{cookiePaths: cookiePaths, redirectURL: finalRedirectURL, secure: secure}, err\n}\n\n// ValidateRedirectURL validates the optional post-logout redirect URL supplied by an operator.\nfunc ValidateRedirectURL(redirectURL string) error {\n\tif redirectURL != \"\" && !isAbsoluteHTTPURL(redirectURL) {\n\t\treturn fmt.Errorf(\"logout redirect URL must be an absolute HTTP(S) URL without user info or a fragment: %q\", redirectURL)\n\t}\n\treturn nil\n}\n\nfunc isAbsoluteHTTPURL(rawURL string) bool {\n\t_, ok := parseAbsoluteHTTPURL(rawURL)\n\treturn ok\n}\n\nfunc parseAbsoluteHTTPURL(rawURL string) (*url.URL, bool) {\n\tparsedURL, err := url.Parse(rawURL)\n\tif err != nil || parsedURL.Hostname() == \"\" || parsedURL.User != nil || parsedURL.Fragment != \"\" ||\n\t\t(!strings.EqualFold(parsedURL.Scheme, \"http\") && !strings.EqualFold(parsedURL.Scheme, \"https\")) {\n\t\treturn nil, false\n\t}\n\treturn parsedURL, true\n}\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/logout/logout.go#L22-L58","documentation":"ValidateRedirectURL checks the operator-supplied post-logout redirect URL configured on the Argo Server. It rejects any non-empty value that is not an absolute HTTP(S) URL (the shared parseAbsoluteHTTPURL helper also excludes user info and fragments). This guards against malformed or unsafe logout redirects.","triggerScenarios":"Starting `argo server` with a logout redirect URL (e.g. via --redirect-url-after-logout or env var) that is relative (\"/logged-out\"), not http(s) (\"ftp://x\"), contains userinfo (\"https://user:pass@host\") or a fragment (\"https://host#frag\").","commonSituations":"Operators copying OIDC provider logout URLs with fragments, mistyping the flag, or setting a relative path believing relative redirects are allowed.","solutions":["Set the URL to a fully qualified absolute URL starting with http:// or https://","Remove any #fragment and user:password@ userinfo from the URL","If no post-logout redirect is desired, leave the value empty (empty is valid)"],"exampleFix":"// before\nARGO_SERVER_REDIRECT_URL_AFTER_LOGOUT=/goodbye\n// after\nARGO_SERVER_REDIRECT_URL_AFTER_LOGOUT=https://sso.example.com/logout","handlingStrategy":"validation","validationCode":"u, err := url.Parse(cfg.LogoutRedirectURL)\nif cfg.LogoutRedirectURL != \"\" && (err != nil || (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" || u.User != nil || u.Fragment != \"\") {\n    return fmt.Errorf(\"invalid logout redirect URL: %q\", cfg.LogoutRedirectURL)\n}","typeGuard":"func isSafeAbsoluteURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && raw != \"\" && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\" && u.User == nil && u.Fragment == \"\"\n}","tryCatchPattern":"if err := logout.ValidateRedirectURL(cfg.LogoutRedirectURL); err != nil {\n    log.Fatalf(\"bad logout redirect URL: %v\", err)\n}","preventionTips":["Always configure full https:// URLs for operator-provided redirects","Strip #fragments and credentials before persisting config","Validate the value at config-load time, not at logout time"],"tags":["server","oidc","url-validation","config"],"backgroundTag":"invalid-url","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}