]> git.ipfire.org Git - thirdparty/git.git/commitdiff
wincred: prevent silent credential loss when storing OAuth tokens
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 16 Jul 2026 14:27:51 +0000 (14:27 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Jul 2026 18:31:32 +0000 (11:31 -0700)
When `git credential approve` hands the wincred helper a password
together with an `oauth_refresh_token`, the OAuth branch of
`store_credential()` writes one WCHAR past the allocation while
formatting both fields into a single `CredentialBlob`. On Windows
this trips heap verification and tears the helper down with status
`0xC0000374`; `approve` masks the failure, so the credential the
user meant to save never reaches `CredWriteW()` and the next
session prompts for it again.

The bug has the same shape as the one fixed in the previous commit:
the allocation leaves no room for the terminating NUL, and the
`sizeOfBuffer` argument to `_snwprintf_s()` is a byte count where
the API expects a WCHAR count, which lets the safe-CRT runtime
write the terminator out of bounds.

Apply the same remedy d22a488482 (wincred: avoid memory corruption,
2025-11-17) applied in `get_credential()`: allocate `(wlen + 1) *
sizeof(WCHAR)` bytes and pass `wlen + 1` as the destination
capacity in WCHARs.

This closes the second of the two heap writes tracked under
GHSA-rxqw-wxqg-g7hw.

Assisted-by: Opus 4.7
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/credential/wincred/git-credential-wincred.c

index 190bbccdf9e84c020f6e014225090a8f4e9be504..22eb27ca31dea01d8bce2d7c89426ff96caa0af7 100644 (file)
@@ -208,8 +208,8 @@ static void store_credential(void)
 
        if (oauth_refresh_token) {
                wlen = _scwprintf(L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
-               secret = xmalloc(sizeof(WCHAR) * wlen);
-               _snwprintf_s(secret, sizeof(WCHAR) * wlen, wlen, L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
+               secret = xmalloc((wlen + 1) * sizeof(WCHAR));
+               _snwprintf_s(secret, wlen + 1, wlen, L"%s\r\noauth_refresh_token=%s", password, oauth_refresh_token);
        } else {
                secret = _wcsdup(password);
        }