fix(gitlab): stop leaking the PAT (SSRF-scoped MR fetch, header-based clone auth) - #314
Merged
Merged
Conversation
…host, keep clone token out of the URL Three security issues in the GitLab provider (Tencent#307): 1. [HIGH] SSRF / credential exfiltration in mr-fetch.ts — fetchGitLabMR derived the API base (and sent the PAT) from the host in the user-supplied MR URL, with no check against the configured instance. A hand-crafted MR URL on an attacker-controlled host would receive the token. Now the URL host must match GITLAB_HOST (GITLAB_URL / TEAMAI_GITLAB_HOST, default gitlab.com) or the fetch is rejected before any network call. We still derive scheme/port from the URL so self-hosted instances keep working — but only for the trusted host. 2. [MEDIUM] Credential persistence in gitlab-api.ts — gitlabRepoClone embedded the token in the clone URL (oauth2:<token>@...), which git writes into the cloned repo's .git/config for every later fetch/push. Inject it via `-c http.extraHeader=Authorization: Basic <base64(oauth2:token)>` instead, so the token never enters the URL or .git/config. Mirrors clone.ts. 3. [MEDIUM] Inconsistent redaction in gitlab-api.ts — the clone-error path used an inline `oauth2:[^@]+@` regex. Use the shared sanitizeGitUrl from utils/redact.ts so redaction coverage stays consistent with clone.ts. Tests: updated gitlab-provider.test.ts to assert the header-based auth, the clean clone URL, and the SSRF rejection; added gitlab-clone-realspawn.test.ts which runs a REAL git spawn against a fake `git` on PATH and confirms the token never appears in the argv/URL (only base64 in the extraHeader) and that the surfaced error is sanitized. docs/providers.md updated to match. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three security issues in the GitLab provider added in #307. All three were flagged by automated security review; none are in scope of any other open PR.
1. [HIGH] SSRF / credential exfiltration —
src/providers/gitlab/mr-fetch.tsfetchGitLabMRderived the API base and sent the PAT to whatever host appeared in the user-supplied MR URL, with no check against the configured instance. A hand-crafted MR URL pointing at an attacker-controlled host would receive the token.Fix: the URL host must match the configured instance (
GITLAB_URL/TEAMAI_GITLAB_HOST, defaultgitlab.com), or the fetch is rejected before any network call. Scheme/port are still derived from the URL so self-hosted instances keep working — but only for the trusted host.2. [MEDIUM] Credential persistence in
.git/config—src/providers/gitlab/gitlab-api.tsgitlabRepoCloneembedded the token in the clone URL (oauth2:<token>@…), which git writes into the cloned repo's.git/configand reuses for every later fetch/push.Fix: inject the token via
-c http.extraHeader=Authorization: Basic <base64(oauth2:token)>instead, so it never enters the URL or.git/config. Mirrors the existinghttp.extraHeaderpattern inclone.ts.3. [MEDIUM] Inconsistent redaction —
src/providers/gitlab/gitlab-api.tsThe clone-error path used an inline
oauth2:[^@]+@regex. Now uses the sharedsanitizeGitUrlfromutils/redact.tsfor consistent coverage.Test plan
npx tsc --noEmit— no errors insrc/(test-file vitest-drift errors are pre-existing, unrelated)npx vitest run— 2138 passed; the only failures are the pre-existing iwiki/import vitest-4.x drift files, unaffected by this changegitlab-provider.test.ts— asserts header-based auth, clean clone URL, and the SSRF rejection (token never sent to a non-configured host)gitlab-clone-realspawn.test.ts— a realgitspawn against a fakegitonPATH, confirming the token never appears in the argv/URL (only base64 insidehttp.extraHeader) and the surfaced error is sanitizeddocs/providers.mdupdated to match the new clone auth and MR-host behavior🤖 Generated with Claude Code