git-ecosystem/git-credential-manager · error · Trace2Exception

Unencrypted HTTP is not recommended for GitHub. Ensure the…

Error message

Unencrypted HTTP is not recommended for GitHub. Ensure the repository remote URL is using HTTPS or see {Constants.HelpUrls.GcmUnsafeRemotes} about how to allow unsafe remotes.

What it means

GitHubHostProvider.GenerateCredentialAsync refuses to acquire credentials for an unencrypted http:// remote URL unless the user explicitly opts in, because credentials would be transmitted in clear text. It throws a Trace2Exception directing the user to switch the remote to HTTPS or read the GCM documentation on allowing unsafe remotes.

Solutions

  1. Change the remote to HTTPS: git remote set-url origin https://github.com/owner/repo.git
  2. If plain HTTP is truly intended (e.g. internal proxy), allow it via config: git config --global credential.allowUnsafeRemotes true (or GCM_ALLOW_UNSAFE_REMETES env var GCM_ALLOW_UNSAFE_REMETES -> actually GCM_ALLOW_UNSAFE_REMETES documented as credential.allowUnsafeRemotes).
  3. Verify the remote URL with 'git remote -v' and correct the scheme typo.
  4. Use the documented help page (Constants.HelpUrls.GcmUnsafeRemotes) for environment-specific instructions.

Example fix

// before
git remote set-url origin http://github.com/owner/repo.git

// after
git remote set-url origin https://github.com/owner/repo.git
// or, only if intentional:
git config --global credential.allowUnsafeRemotes true
Defensive patterns

Strategy: validation

Validate before calling

var remoteUrl = new Uri(run("git remote get-url origin"));
if (remoteUrl.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase))
{
    // fix before invoking GCM
    run($"git remote set-url origin {new UriBuilder(remoteUrl) { Scheme = "https", Port = -1 }.Uri}");
}

Try / catch

try
{
    var cred = await provider.GenerateCredentialAsync(remoteUri, authModes);
}
catch (Exception ex) when (ex.Message.Contains("Unencrypted HTTP"))
{
    // rewrite remote to HTTPS or enable credential.allowUnsafeRemotes deliberately
}

Prevention

When it happens

Trigger: git operation against a GitHub remote whose URL scheme is http:// while _context.Settings.AllowUnsafeRemotes is false (the default). Happens whenever GCM must generate a credential for such a remote.

Common situations: Cloning/pushing to 'http://github.com/...' by typo or company mirror proxy; legacy internal servers using plain HTTP; stale remote URLs left over from configuration migration.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/c8a7ed9d712fd3f0. Report an issue: GitHub.

Appendix: source

Thrown at src/GitHub/GitHubHostProvider.cs:293

                _context.Trace.WriteLine("Credential was successfully erased.");
            }
            else
            {
                _context.Trace.WriteLine("No credential was erased.");
            }

            return Task.CompletedTask;
        }

        internal /* for testing purposes */  async Task<ICredential> GenerateCredentialAsync(Uri remoteUri, string userName)
        {
            ThrowIfDisposed();

            // We should not allow unencrypted communication and should inform the user
            if (!_context.Settings.AllowUnsafeRemotes &&
                StringComparer.OrdinalIgnoreCase.Equals(remoteUri.Scheme, "http"))
            {
                throw new Trace2Exception(_context.Trace2,
                    "Unencrypted HTTP is not recommended for GitHub. " +
                    "Ensure the repository remote URL is using HTTPS " +
                    $"or see {Constants.HelpUrls.GcmUnsafeRemotes} about how to allow unsafe remotes.");
            }

            string service = GetServiceName(remoteUri);

            AuthenticationModes authModes = await GetSupportedAuthenticationModesAsync(remoteUri);

            AuthenticationPromptResult promptResult = await _gitHubAuth.GetAuthenticationAsync(remoteUri, userName, authModes);

            switch (promptResult.AuthenticationMode)
            {
                case AuthenticationModes.Basic:
                    GitCredential patCredential = await GeneratePersonalAccessTokenAsync(remoteUri, promptResult.Credential);

                    // HACK: Store the PAT immediately in case this PAT is not valid for SSO.
                    // We don't know if this PAT is valid for SAML SSO and if it's not Git will fail

View on GitHub (pinned to e8ce762cd0)