{"record":{"id":"c84bfce2c7131be6","repo":"cloudflare/cloudflared","slug":"currently-cloudflare-tunnel-does-not-support-s-pr","errorCode":null,"errorMessage":"Currently Cloudflare Tunnel does not support %s protocol.","messagePattern":"Currently Cloudflare Tunnel does not support (.+?) protocol\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"validation/validation.go","lineNumber":155,"sourceCode":"\t\t\thostname, err = ValidateHostname(host)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"URL %s has invalid format\", originUrl)\n\t\t\t}\n\t\t\t// This is why the path is preserved when `originUrl` doesn't have a schema.\n\t\t\t// Using `parsedUrl.Port()` here, instead of `port`, would remove the path\n\t\t\treturn fmt.Sprintf(\"%s://%s\", defaultScheme, net.JoinHostPort(hostname, port)), nil\n\t\t}\n\t}\n\n}\n\nfunc validateScheme(scheme string) error {\n\tfor _, protocol := range supportedProtocols {\n\t\tif scheme == protocol {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"Currently Cloudflare Tunnel does not support %s protocol.\", scheme)\n}\n\nfunc validateIP(scheme, host, port string) (string, error) {\n\tif scheme == \"\" {\n\t\tscheme = defaultScheme\n\t}\n\tif port != \"\" {\n\t\treturn fmt.Sprintf(\"%s://%s\", scheme, net.JoinHostPort(host, port)), nil\n\t} else if strings.Contains(host, \":\") {\n\t\t// IPv6\n\t\treturn fmt.Sprintf(\"%s://[%s]\", scheme, host), nil\n\t}\n\treturn fmt.Sprintf(\"%s://%s\", scheme, host), nil\n}\n\n// Access checks if a JWT from Cloudflare Access is valid.\ntype Access struct {\n\tverifier *oidc.IDTokenVerifier","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/validation/validation.go#L137-L173","documentation":"validateScheme checks the URL's scheme against cloudflared's supported protocol list (http, https, rdp, ssh, smb, tcp). Any other scheme — file, ftp, ws, wss, mailto, etc. — is rejected with this error. This is a deliberate restriction: Cloudflare Tunnel can only proxy these protocols.","triggerScenarios":"ValidateUrl('ftp://example.com'), 'ws://...', 'file:///path', or any URL where the text before '://' is not in the supported list. Also fires via NewAccessValidator if the domain/issuer uses an unsupported scheme.","commonSituations":"Users assuming websocket (ws://) or ftp URLs work as tunnel origins, copy-pasting browser URLs with unsupported schemes, or typos like 'htp://'.","solutions":["Switch the origin to a supported scheme: http, https, rdp, ssh, smb, or tcp","For raw TCP/WebSocket services, use 'tcp' (or 'ws' semantics over http) as the scheme in config","Fix typos in the scheme (htp → http)","If the service runs on plain HTTP, simply omit the scheme and let the default http:// apply"],"exampleFix":"// before\nValidateUrl(\"ftp://files.example.com\") // unsupported protocol\n// after\nValidateUrl(\"tcp://files.example.com:21\")","handlingStrategy":"validation","validationCode":"var supported = map[string]bool{\"http\":true,\"https\":true,\"rdp\":true,\"ssh\":true,\"smb\":true,\"tcp\":true}\nfunc schemeSupported(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"\" || supported[strings.ToLower(u.Scheme)])\n}","typeGuard":null,"tryCatchPattern":"if _, err := validation.ValidateUrl(origin); err != nil {\n    if strings.Contains(err.Error(), \"does not support\") {\n        return fmt.Errorf(\"origin %q uses an unsupported scheme; use http/https/rdp/ssh/smb/tcp\", origin)\n    }\n}","preventionTips":["Check the scheme against the supported list when authoring config","Use tcp for generic TCP services instead of ftp/ws-style schemes","Document supported schemes where config is edited"],"tags":["url","scheme","unsupported-protocol","configuration"],"backgroundTag":"unsupported-operation","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}