anthropics / anthropics/claude-code-action

commit_files/delete_files fail under use_commit_signing when the branch name contains `#`: git ref URLs are built without percent-encoding

Aperta
#1,777 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug mcp p2
Lingua principale
TypeScript
Stelle
8.9k
Fork
2.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

**Type:** bug
**Severity:** medium (commit signing is unusable on affected branches)
**Area:** `src/mcp/github-file-ops-server.ts`, `src/mcp/update-git-reference.ts`
**Effort:** small

## Summary

`validateBranchName` explicitly allows `#` in branch names (`src/github/operations/branch.ts`, added in #1167: "valid per git-check-ref-format and commonly used in branch names like `fix/#123-description`"). The file ops MCP server and `updateGitReference` then interpolate the branch, base branch and default branch **raw** into `fetch()` URLs:

```ts
// src/mcp/github-file-ops-server.ts (getOrCreateBranchRef)
const refUrl = `${GITHUB_API_URL}/repos/${owner}/${repo}/git/refs/heads/${branch}`; // line 69
const baseRefUrl = `${GITHUB_API_URL}/repos/${owner}/${repo}/git/refs/heads/${baseBranch}`; // line 90
const defaultRefUrl = `${GITHUB_API_URL}/repos/${owner}/${repo}/git/refs/heads/${defaultBranch}`; // line 122

// src/mcp/update-git-reference.ts
const updateRefUrl = `${GITHUB_API_URL}/repos/${owner}/${repo}/git/refs/heads/${branch}`; // line 47
```

In a URL, `#` starts the fragment, which is never sent on the wire. For `fix/#123-description` GitHub receives `GET /repos/o/r/git/refs/heads/fix/`.

## Reproduction

Run the action with `use_commit_signing: true` on a PR whose head branch is `fix/#123-description` and let Claude call `commit_files` (or `delete_files`). Driving the real server over stdio against a fake API that mimics GitHub's documented prefix-match behaviour for `git/refs/heads/` (verified read-only: `gh api repos/anthropics/claude-code-action/git/refs/heads/ma` returns an array):

```
BRANCH_NAME env : fix/#123-description
requests received : [ "GET /repos/o/r/git/refs/heads/fix/" ]
expected first request: GET /repos/o/r/git/refs/heads/fix/%23123-description
tool isError : true
tool text : Error: undefined is not an object (evaluating '(await refResponse.json()).object.sha')
```

If no sibling `fix/*` branch exists GitHub returns 404 instead; the server then tries to *create* `refs/heads/fix/#123-description` and gets 422 "Reference already exists". Either way the tool cannot commit. `BASE_BRANCH` containing `#` (line 90) is the same shape as the default branch reported in #1314.

## Expected

The request is sent as `GET /repos/o/r/git/refs/heads/fix/%23123-description`, the ref resolves, and the commit is created.

## Root cause

String interpolation into `fetch()` URLs. The octokit call sites elsewhere are unaffected because octokit percent-encodes template parameters. `encodeBranchNameForUrl` in `src/github/operations/comments/common.ts` already implements the right per-segment encoding (it was applied to the **link** URLs in #1713), but not to these four API URLs. PR #1326 targeted the same sites in 2026-05 but bundled unrelated changes and was closed without landing.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.