{"record":{"id":"c40f9a8090040649","repo":"siyuan-note/siyuan","slug":"oauth-revocation-endpoint-must-use-https-or-loopba","errorCode":null,"errorMessage":"OAuth revocation endpoint must use HTTPS or loopback HTTP","messagePattern":"OAuth revocation endpoint must use HTTPS or loopback HTTP","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/client/oauth.go","lineNumber":741,"sourceCode":"\t\t\tfor _, credential := range credentials {\n\t\t\t\tif err := revokeOAuthCredential(ctx, client, credential); err != nil {\n\t\t\t\t\trevokeErr = errors.Join(revokeErr, err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif revokeErr != nil {\n\t\t\t\tlogging.LogWarnf(\"mcp oauth: revoke credentials for server [%s] failed: %s\", serverID, revokeErr)\n\t\t\t}\n\t\t}()\n\t}\n\treturn nil\n}\n\nfunc revokeOAuthCredential(ctx context.Context, client *http.Client, credential oauthCredential) error {\n\tif credential.RevocationEndpoint == \"\" {\n\t\treturn nil\n\t}\n\tif !isSecureOAuthEndpoint(credential.RevocationEndpoint) {\n\t\treturn fmt.Errorf(\"OAuth revocation endpoint must use HTTPS or loopback HTTP\")\n\t}\n\tvar result error\n\tfor _, token := range []struct {\n\t\tvalue string\n\t\thint  string\n\t}{{credential.RefreshToken, \"refresh_token\"}, {credential.AccessToken, \"access_token\"}} {\n\t\tif token.value == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tvalues := url.Values{\"token\": {token.value}, \"token_type_hint\": {token.hint}}\n\t\tapplyOAuthClientAuthentication(values, nil, credential)\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, credential.RevocationEndpoint, strings.NewReader(values.Encode()))\n\t\tif err != nil {\n\t\t\tresult = errors.Join(result, err)\n\t\t\tcontinue\n\t\t}\n\t\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\t\tapplyOAuthClientAuthentication(nil, req, credential)","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/mcp/client/oauth.go#L723-L759","documentation":"The configured OAuth revocation endpoint URL is not HTTPS and is not a loopback HTTP address. `isSecureOAuthEndpoint` requires HTTPS for any non-loopback host so that refresh/access tokens sent during revocation are never transmitted in cleartext over a network.","triggerScenarios":"`revokeOAuthCredential` is called (during `DisconnectMCPOAuth`) with a credential whose `RevocationEndpoint` scheme is `http://` pointing at a non-localhost host, or an unsupported scheme like `ftp`.","commonSituations":"On-premise/dev IdP advertising an `http://` revocation endpoint. A mis-pasted revocation URL missing the `s` in `https://`. A reverse proxy that terminates TLS but whose published metadata still lists the internal `http://` URL.","solutions":["Correct the IdP's published revocation endpoint metadata to use `https://`.","If testing locally, point the revocation endpoint at `http://localhost:...` or `http://127.0.0.1:...` (loopback is permitted).","Ensure the reverse proxy advertises the public `https://` URL in metadata even when it forwards internally over HTTP."],"exampleFix":"// before\nRevocationEndpoint: \"http://idp.internal:8080/revoke\"\n// after\nRevocationEndpoint: \"https://idp.internal/revoke\"","handlingStrategy":"validation","validationCode":"// Enforce HTTPS (or loopback) before storing a revocation endpoint.\nfunc assertSecureRevokeURL(endpoint string) error {\n    u, err := url.Parse(endpoint)\n    if err != nil {\n        return err\n    }\n    if u.Scheme == \"https\" {\n        return nil\n    }\n    if u.Scheme == \"http\" && (strings.EqualFold(u.Hostname(), \"localhost\") || net.ParseIP(u.Hostname()).IsLoopback()) {\n        return nil\n    }\n    return errors.New(\"revocation endpoint must use HTTPS or loopback HTTP\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always prefer https:// for revocation endpoints in published metadata.","Use loopback http:// only for local development.","Make reverse proxies advertise their public https:// URL."],"tags":["oauth","mcp","security","transport-security"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}