Skip to content

Git fails to detect valid credentials when they are stored in a local file with Windows (CRLF) line endings #6409

Description

@i80487

Existing issues matching what you're seeing

  • I was not able to find an open or closed issue matching what I'm seeing

Git for Windows version

git version 2.55.0.windows.5
cpu: x86_64
built from commit: 32c4f7689275d233577576630e1ac5b7eb354eb0
sizeof-long: 4
sizeof-size_t: 8
shell-path: D:/git-sdk-64-build-installers/usr/bin/sh
rust: disabled
feature: fsmonitor--daemon
gettext: enabled
libcurl: 8.21.0
OpenSSL: OpenSSL 3.5.7 9 Jun 2026
zlib: 1.3.2
SHA-1: SHA1_DC
SHA-256: SHA256_BLK
default-ref-format: files
default-hash: sha1

Windows version

Windows 10

Windows CPU architecture

x86_64 (64-bit)

Additional Windows version information

Microsoft Windows 10 Entreprise LTSC - Version 10.0.19044.7663

Options set during installation

Editor Option: Notepad++
Custom Editor Path: 
Default Branch Option:  
Path Option: Cmd
SSH Option: OpenSSH
Tortoise Option: false
CURL Option: WinSSL
CRLF Option: CRLFCommitAsIs
Bash Terminal Option: ConHost
Git Pull Behavior Option: Merge
Use Credential Manager: Disabled
Performance Tweaks FSCache: Enabled
Enable Symlinks: Disabled
Enable FSMonitor: Disabled

Other interesting things

Suspected cause:

The credentials file is read by parse_credential_file() in builtin/credential-store.c. At line 33, it uses strbuf_getline_lf(). strbuf_getline_lf() removes the trailing LF character but preserves the preceding CR character.

Therefore, the following line:

https://user:token@dev.azure.com\r\n

is passed to the URL parser as:

https://user:token@dev.azure.com\r

The trailing \r becomes part of the parsed host (dev.azure.com\r). This does not match the requested host (dev.azure.com) when credential_match() performs its exact string comparison. The credential helper consequently returns no credentials, and Git falls back to prompting the user for a password.

Possible fix:

I think it would be appropriate to use strbuf_getline() instead of strbuf_getline_lf() when reading the credentials file, because strbuf_getline() removes both LF and CRLF line endings.

Note:

t/t0302-credential-store.sh should probably be updated because it currently contains a test (line 146) that explicitly expects a host-only "credential with CRLF line endings to be invalid" ??! However, the same credential file with a LF is valid.

Few lines later (line 163), there is another test "get: credentials with path and DOS line endings are valid" !

It all seems rather inconsistant…

Terminal/shell

cmd.exe and/or TortoiseGit 2.19.1.0 64-bit

Commands that trigger the issue

I downloaded and installed "Git for Windows 2.55.0" and generated a Personal Access Token (PAT) in Azure DevOps. I then created a credentials file using a Windows text editor (Notepad++).

The file contains only this character string followed by a newline:

https://COMPANY:PAT@dev.azure.com

I saved the file as "credentials" without any extension. It was automatically saved with Windows-style CRLF line endings, which I didn't notice at the time and honestly never pay attention to anyway.

I configured Git to use this file:

git config --global credential.helper "store --file C:/Users/xxxxx/.pat/credentials"

I then tried to clone an Azure DevOps repository:

git clone https://organization@dev.azure.com/company/project/_git/repo

Expected behaviour

Git should read the configured credentials file and attempt to recognize the username/organization, PAT, and domain regardless of whether the file uses Unix (LF) or Windows (CRLF) line endings.

Actual behaviour

Git does not recognize the PAT and prompts for a password. At that moment, I was thinking : "A password? What password exactly? As far as I know, there is no password involved here (Azure DevOps website). Only a PAT stored in my credentials file! I don’t know the password!". As a result, the clone operation fails.

After spending more than one hour debugging the problem, I finally noticed a difference in the line endings by comparing the file with another credentials file that I knew worked. I then changed the line ending from CRLF to LF, tried cloning the repository again, and the operation succeeded.

Repository

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions