Reduce OAuth scope to avoid Windows credential size limit (#58541)

I encountered an issue where I couldn't sign in to ChatGPT Subscription
on Windows:

```
ChatGPT subscription sign-in failed to persist credentials: 
Failed to write credentials to Windows Credential Manager: 
占位程序接收到错误数据。 (0x800706F7)
```

Interestingly, only one of my three ChatGPT accounts had this problem —
the other two signed in successfully.

## What I Found

After investigating, I noticed that the OAuth scope in
`openai_subscribed.rs` requests 6 permissions:

```
openid profile email offline_access api.connectors.read api.connectors.invoke
```

I wrote a test script to measure token sizes and found that:
- With 6 scopes: my problematic account's token was **2578 bytes**
- With 4 scopes (removing `api.connectors.read` and
`api.connectors.invoke`): the same token was **2516 bytes**

Since Windows Credential Manager has a 2560-byte limit
(`CRED_MAX_CREDENTIAL_BLOB_SIZE`), this could explain why some accounts
fail while others succeed — it depends on the base token size.

## My Hypothesis

The issue seems to be that:
- Error code `0x800706F7` = `RPC_X_BAD_STUB_DATA` (size limit, not
format)
- Accounts with larger base tokens exceed the limit when the extra 48
chars are added
- Accounts with smaller base tokens still fit, which is why this isn't
universally reproducible

I'm not 100% certain this is the root cause, but the evidence seems to
point in this direction.

## Proposed Fix

I removed `api.connectors.read` and `api.connectors.invoke` from the
OAuth scope, since:
- These scopes don't appear to be used by Zed's current ChatGPT
integration
- OpenCode (another tool using the same OAuth provider) successfully
uses only 4 scopes
- This fix allowed my problematic account to sign in

However, I'd like to ask the maintainers:
- Are there plans to use OpenAI Connectors API in the future?
- Are there security or compliance reasons for requesting these extra
scopes?

If the answer is yes to either, we'd need a different approach (e.g.,
splitting credentials, using encrypted file storage, or checking token
size before storage).

## Testing

- [x] Verified my problematic account now signs in successfully
- [x] Verified my other accounts still work
- [x] Ran `cargo check -p language_models` (compilation successful)
- [ ] Would appreciate help testing on macOS/Linux

## Questions

1. Does this analysis make sense?
2. Are there any other considerations I'm missing?
3. Would it be helpful to add a size check with a clearer error message
for future cases?

I'm happy to adjust this approach based on your feedback.

Release Notes:

- Fixed ChatGPT Subscription sign-in failing on Windows for some
accounts by removing unused OAuth scopes (`api.connectors.read`,
`api.connectors.invoke`) that pushed JWT tokens over Windows Credential
Manager's limit.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
ArtinandSmit Barmase authored and GitHub committed 2026-07-03 19:38:42 +00:00
1 parent 917863a6bd
commit 03d11509fa
2 files changed
+15 -4

No files matched your search

+9
View File
@@ -741,6 +741,15 @@ impl Platform for WindowsPlatform {
}
fn write_credentials(&self, url: &str, username: &str, password: &[u8]) -> Task<Result<()>> {
// CredWriteW rejects larger blobs with the opaque RPC error
// 0x800706F7 "The stub received bad data", so fail with a clear
// message instead.
if password.len() > CRED_MAX_CREDENTIAL_BLOB_SIZE as usize {
return Task::ready(Err(anyhow!(
"credential for {url} is {} bytes, which exceeds the Windows Credential Manager limit of {CRED_MAX_CREDENTIAL_BLOB_SIZE} bytes",
password.len()
)));
}
let password = password.to_vec();
let mut username = username.encode_utf16().chain(Some(0)).collect_vec();
let mut target_name = windows_credentials_target_name(url)
@@ -760,10 +760,12 @@ async fn do_oauth_flow(
.query_pairs_mut()
.append_pair("client_id", CLIENT_ID)
.append_pair("redirect_uri", &redirect_uri)
.append_pair(
"scope",
"openid profile email offline_access api.connectors.read api.connectors.invoke",
)
// Deliberately excludes `api.connectors.read api.connectors.invoke`
// (which Codex CLI requests): extra scopes inflate the
// access-token JWT, and the serialized credentials must fit within
// Windows Credential Manager's 2560-byte blob limit
// (CRED_MAX_CREDENTIAL_BLOB_SIZE). See #58541.
.append_pair("scope", "openid profile email offline_access")
.append_pair("response_type", "code")
.append_pair("code_challenge", &challenge)
.append_pair("code_challenge_method", "S256")