{"record":{"id":"02c9767d20d08bc0","repo":"stablyai/orca","slug":"pull-request-fetch-remote-must-not-start-with","errorCode":null,"errorMessage":"Pull request fetch remote must not start with \"-\".","messagePattern":"Pull request fetch remote must not start with \"-\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/github/pr-head-tracking-ref.ts","lineNumber":50,"sourceCode":"  }\n  if (!sshGitProvider) {\n    throw new Error('SSH Git provider is not available. Reconnect to this target and try again.')\n  }\n  await sshGitProvider.fetchRemoteTrackingRef(repo.path, remote, branch, ref)\n}\n\nexport async function fetchGitHubPullRequestHeadRef(\n  repo: { path: string; connectionId?: string | null },\n  sshGitProvider: SshGitProvider | null | undefined,\n  remote: string,\n  prNumber: number,\n  options: { localGitExecOptions?: LocalGitExecOptions } = {}\n): Promise<string> {\n  if (!isValidReviewHeadNumber(prNumber)) {\n    throw new Error(`Invalid pull request number: ${String(prNumber)}`)\n  }\n  if (!isSafeReviewHeadFetchRemote(remote)) {\n    throw new Error('Pull request fetch remote must not start with \"-\".')\n  }\n  if (!repo.connectionId) {\n    const localGitExecOptions = options.localGitExecOptions ?? { cwd: repo.path }\n    const remoteComponent = await getReviewHeadRemoteComponent(remote, localGitExecOptions)\n    // Why: return the same path the fetch wrote so callers don't re-resolve identity.\n    const localRef = githubPullRequestHeadLocalRef(remoteComponent, prNumber)\n    await gitExecFileAsync(\n      ['fetch', '--no-tags', remote, `+refs/pull/${prNumber}/head:${localRef}`],\n      {\n        ...localGitExecOptions,\n        timeout: REVIEW_HEAD_FETCH_TIMEOUT_MS\n      }\n    )\n    return localRef\n  }\n  if (!sshGitProvider) {\n    throw new Error('SSH Git provider is not available. Reconnect to this target and try again.')\n  }","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/github/pr-head-tracking-ref.ts#L32-L68","documentation":"Thrown by fetchGitHubPullRequestHeadRef when isSafeReviewHeadFetchRemote rejects the remote name — specifically, a remote beginning with `-`. The remote is interpolated directly into a `git fetch` argument list (`['fetch', '--no-tags', remote, ...]`), so a leading dash would be parsed by git as an option rather than a remote name. This is a classic argv-injection / option-injection guard.","triggerScenarios":"A remote named `-something` in git config (malicious or accidental); a remote name sourced from user input or a deep link without sanitization; a corrupted remotes payload; testing code that passes a flag-shaped string as the remote.","commonSituations":"Adversarial or malformed git config; a deep-link or extension API supplying an unvalidated remote name; misconfigured remote added via `git remote add -foo`.","solutions":["Inspect `git remote -v` and remove/rename any remote whose name starts with `-`.","At the trust boundary (deep links, extension input), validate remote names against git-check-ref-format rules and reject leading dashes.","Re-add the remote with a safe name via `git remote rename` or remove + add."],"exampleFix":"// before\nawait fetchGitHubPullRequestHeadRef(repo, provider, remote, prNumber)\n\n// after\nif (!isSafeReviewHeadFetchRemote(remote)) {\n  throw new Error(`Refusing unsafe remote name: ${remote}`)\n}\nawait fetchGitHubPullRequestHeadRef(repo, provider, remote, prNumber)","handlingStrategy":"validation","validationCode":"import { isSafeReviewHeadFetchRemote } from '../../shared/review-head-tracking-ref'\nfunction assertSafeRemote(remote: string) {\n  if (!isSafeReviewHeadFetchRemote(remote)) {\n    throw new Error(`Refusing unsafe remote name: ${remote}`)\n  }\n}","typeGuard":"function isSafeRemoteName(name: unknown): name is string {\n  return typeof name === 'string' && name.length > 0 && !name.startsWith('-')\n}","tryCatchPattern":"if (!isSafeRemoteName(remote)) {\n  toast.error('Unsafe remote name.')\n  return\n}\nawait fetchGitHubPullRequestHeadRef(repo, provider, remote, prNumber)","preventionTips":["Never construct remote names from untrusted input without a leading-dash check.","Run `git remote -v` and remove any remote whose name starts with `-`.","Validate at the trust boundary (deep links, extension API) using git-check-ref-format rules."],"tags":["github","git","security","argv-injection","option-injection","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}