-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Bug description
gh-scoped-creds cannot coexist with other Git credential helpers that require useHttpPath = true, such as git-credential-github-app. When both are configured in the same environment, gh-scoped-creds fails to provide credentials, and Git prompts the user for username/password.
This prevents JupyterHub deployments from offering both:
- Pull access from organization private repos (via git-credential-github-app or similar)
- Push access to user repos (via gh-scoped-creds)
How to reproduce
-
Configure a system-level credential helper that requires
useHttpPath = truein/srv/conda/etc/gitconfig:[credential "https://github.com"] helper = !git-credential-github-app --app-key-file /path/to/key.pem --app-id 12345 useHttpPath = true
-
Install gh-scoped-creds and run the authentication flow:
import gh_scoped_creds %ghscopedcreds --client-id <your-client-id>
-
Attempt to clone a private repository that the user has access to:
git clone https://github.com/username/private-repo
Expected behaviour
Git should use the gh-scoped-creds OAuth token to authenticate and successfully clone the repository without prompting for credentials.
Actual behaviour
Git prompts for username and password:
Username for 'https://github.com/username/private-repo':
The gh-scoped-creds token is never used.
Root Cause
When gh-scoped-creds configures Git, it uses Git's built-in credential-store helper:
subprocess.check_call([
"git", "config", "--global",
"credential.https://github.com.helper",
f"store --file={temp_file}"
])This stores credentials as:
https://x-access-token:[email protected]
The problem occurs because:
- The system-level
useHttpPath = truesetting applies globally to all credential helpers - When Git queries for credentials with
useHttpPath = true, it includes the repository path:protocol=https host=github.com path=username/private-repo - Git's
credential-storehelper performs exact matching and requires the path to match - Since gh-scoped-creds stores credentials without a path (because one OAuth token works for all repos), there's no match
- The credential helper returns nothing, and Git falls back to prompting the user
Why Workarounds Don't Work
- Can't disable
useHttpPath- Other credential helpers like git-credential-github-app require it and crash without the path field - Can't store credentials with a path - gh-scoped-creds creates a single OAuth token for all repos, not per-repo credentials
- Can't modify
git credential-store- It's part of Git itself and we can't change its matching behavior
Your personal set up
Container image at https://github.com/berkeley-dsep-infra/biology-user-image.
- OS: Ubuntu 22.04
- Version(s):
- gh-scoped-creds: 4.1
- JupyterHub: 5.3.0
- git: 2.38.1
Full environment
gh-scoped-creds==4.1
jupyterhub==5.3.0
Configuration
System gitconfig (/srv/conda/etc/gitconfig):
[credential "https://github.com"]
helper = !git-credential-github-app --app-key-file /srv/conda/etc/github/github-app-private-key.pem --app-id 229235
useHttpPath = trueUser gitconfig after running %ghscopedcreds (~/.gitconfig):
[credential "https://github.com"]
helper = store --file=/tmp/tmpXXXXXXXXEffective configuration:
$ git config --list --show-origin | grep credential
file:/srv/conda/etc/gitconfig credential.https://github.com.helper=!git-credential-github-app ...
file:/srv/conda/etc/gitconfig credential.https://github.com.usehttppath=true
file:/home/jovyan/.gitconfig credential.https://github.com.helper=store --file=/tmp/tmpXXXXXXXX
Both helpers are present, but the useHttpPath = true setting prevents the store helper from matching.
Logs
Testing credential retrieval directly:
$ echo -e "protocol=https\nhost=github.com\npath=username/private-repo" | git credential fill
Username for 'https://github.com/username/private-repo':The credential helpers return nothing, so Git prompts for credentials.
Testing the store helper directly:
$ cat /tmp/tmpXXXXXXXX
https://x-access-token:[email protected]
$ echo -e "protocol=https\nhost=github.com\npath=username/private-repo" | git credential-store --file=/tmp/tmpXXXXXXXX get
# No output - no match found because path doesn't matchProposed Solution
Replace the use of Git's built-in credential-store with a custom credential helper that:
- Reads the OAuth token from the temporary file (maintaining current security model)
- Ignores the
pathparameter when queried by Git - Returns the token for any GitHub repository
This would allow gh-scoped-creds to work alongside other credential helpers that require useHttpPath = true.
I can submit a PR with the implementation details if you think this is the desired approach.