Skip to content

fix(adapters): ride GitHub PATs in the username slot of clone URLs - #609

Merged
Hydralerne merged 1 commit into
oblien:mainfrom
santhiprakash:fix/git-clone-pat-username
Aug 18, 2026
Merged

fix(adapters): ride GitHub PATs in the username slot of clone URLs#609
Hydralerne merged 1 commit into
oblien:mainfrom
santhiprakash:fix/git-clone-pat-username

Conversation

@santhiprakash

Copy link
Copy Markdown
Contributor

Summary

injectGitToken now rides GitHub PAT/OAuth credentials in the username slot of the clone URL on github.com, keeping x-access-token:<token>@ only for GitHub App installation tokens (ghs_…) and for non-GitHub hosts.

Motivation

GitHub accepts x-access-token as the basic-auth username only for GitHub App installation tokens. A classic PAT (ghp_…) or fine-grained PAT (github_pat_…) in the password slot behind that fixed username is rejected with:

remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed for 'https://github.com/<owner>/<repo>.git/'

So every self-hosted private-repo deployment configured with a user or project clone token (Settings → Clone credentials, or per-project) failed at the git clone step, while the same token worked when used directly outside Openship. Non-ghs_ credentials on github.com now use the https://<token>@github.com/… form GitHub documents for token-only HTTPS auth.

Non-GitHub hosts keep the previous x-access-token:<token>@ form unchanged — they accept an arbitrary username, so changing them is out of scope for this fix.

Related issue

Closes #607

Changes

  • packages/adaptersruntime/git-clone.ts: injectGitToken detects github.com (and subdomains) and, for tokens that are not ghs_-prefixed, sets the token as the URL username with an empty password instead of x-access-token:<token>@. ghs_… tokens and all other hosts are byte-identical to before.
  • runtime/git-clone.test.ts: the x-access-token assertions now use a ghs_… installation token; new cases for ghp_…, github_pat_…, gho_… (username-slot form) and a non-GitHub host regression guard.

Log redaction is unaffected: redactCredentials's userinfo matcher is scheme-generic (scheme://<userinfo>@) and its bare-token patterns match gh[pousr]_…/github_pat_… wherever they appear, so the new URL form is still scrubbed before persistence (verified below).

Verification

A test fails without this change and passes with it — with only the test file applied, 4 tests fail (ghp_…/github_pat_…/gho_… username-slot cases + the assembled clone URL); with the fix, all pass:

$ cd packages/adapters && bun run test src/runtime/git-clone.test.ts
      Test Files  1 passed (1)       Tests  31 passed (31)      # with fix
# source stashed, tests only:
      Test Files  1 failed (1)       Tests  4 failed | 27 passed

Full local gates:

$ bun run test                     # packages/adapters full suite
      Test Files  134 passed (134)
            Tests  2925 passed (2925)
$ bun run --cwd apps/api test test/modules/deployments/build-log-sanitize.test.ts
      Test Files  1 passed (1)      Tests  24 passed (24)
$ bun run --cwd packages/adapters lint   # tsc --noEmit — clean
$ bunx prettier --check <touched files>  # clean

End-to-end against live GitHub, using a temporary private repo and a real gho_… OAuth token (redacted; public repos don't exercise credential checks — verified with an invalid-token control):

# old form (x-access-token:<tok>@) — what main ships today
$ git clone https://x-access-token:<REDACTED>@github.com/<private-repo>.git
Cloning into 'p-form-a'...                        # succeeds for gho_ (tolerated)

# new form (<tok>@) — what this PR produces for non-ghs_ tokens
$ git clone https://<REDACTED>@github.com/<private-repo>.git
Cloning into 'p-form-b'...                        # succeeds — verified working
$ ls p-form-b/README.md && echo "clone OK"

# control: invalid token, old form, private repo — auth IS exercised
$ git clone https://x-access-token:ghp_invalid…@github.com/<private-repo>.git
remote: Invalid username or token. Password authentication is not supported for Git operations.
fatal: Authentication failed

The ghp_…/github_pat_… rejection under the old form is the live repro from #607 (PATs cannot be minted non-interactively, so I could not re-mint one; the control above shows the same server-side check fires on private repos). The ghs_… path is untouched.

Screenshots

Not applicable (backend URL assembly).

Checklist

  • One change per PR — one bug, or one agreed feature, with nothing unrelated bundled in
  • The diff is scoped — no reformatting or lint fixes on lines I wasn't otherwise changing
  • A test fails without this change and passes with it (or I explained above why there isn't one)
  • bun run test, bun run --cwd <workspace> lint, and bun format all pass locally
  • I understand every line of this diff and can explain it in review

GitHub accepts x-access-token as the basic-auth username only for GitHub App
installation tokens (ghs_…). A classic or fine-grained PAT (ghp_…,
github_pat_…) in the password slot behind that fixed username is rejected with
"Invalid username or token. Password authentication is not supported for Git
operations.", so every private-repo deploy configured with a user or project
clone token fails at the git clone step while the same token works when used
directly (oblien#607).

injectGitToken now puts non-ghs_ credentials in the username slot on
github.com (the form GitHub documents for token-only HTTPS auth) and keeps
x-access-token unchanged for installation tokens and non-GitHub hosts, where
an arbitrary username is accepted. Log redaction is unaffected: the
build-log-sanitize userinfo matcher is scheme-generic and the bare-token
patterns match PATs wherever they appear.

Fixes oblien#607
@Hydralerne
Hydralerne merged commit 6f700e5 into oblien:main Aug 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

injectGitToken hardcodes x-access-token username, breaking Git HTTPS clones with Personal Access Tokens (PAT)

2 participants