Sitelet https://github.com/anthropics/claude-code-action/commit/791545dab1ccf50e3ae93efb5073be40520c537d
Skip to content

Commit 791545d

Browse files
authored
fix: allow parentheses in valid branch names (#1710)
Accept parentheses while preserving existing branch-name security checks. Add regression coverage for scoped branch names. Refs #1709
1 parent 2d7a787 commit 791545d

2 files changed

Lines changed: 15 additions & 4 deletions

File tree

‎src/github/operations/branch.ts‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function extractFirstLabel(githubData: FetchDataResult): string | undefined {
2929
*
3030
* Valid branch names:
3131
* - Start with alphanumeric character, underscore, or @ (not dash, to prevent option injection)
32-
* - Contain only alphanumeric, forward slash, hyphen, underscore, period, hash (#), plus (+), comma (,), or at sign (@)
32+
* - Contain only alphanumeric, forward slash, hyphen, underscore, period, hash (#), plus (+), comma (,), at sign (@), or parentheses
3333
* - Do not start or end with a period
3434
* - Do not end with a slash
3535
* - Do not contain '..' (path traversal)
@@ -60,7 +60,7 @@ export function validateBranchName(branchName: string): void {
6060
);
6161
}
6262

63-
// Strict whitelist pattern: alphanumeric or @ start, then alphanumeric/slash/hyphen/underscore/period/hash/plus/comma/at-sign.
63+
// Strict whitelist pattern: alphanumeric or @ start, then alphanumeric/slash/hyphen/underscore/period/hash/plus/comma/at-sign/parentheses.
6464
// # is valid per git-check-ref-format and commonly used in branch names like "fix/#123-description".
6565
// + is valid per git-check-ref-format and generated by Claude Code's EnterWorktree tool when
6666
// converting worktree names containing "/" (e.g. "feat/foo" becomes "worktree-feat+foo").
@@ -72,12 +72,14 @@ export function validateBranchName(branchName: string): void {
7272
// _ is valid per git-check-ref-format anywhere in a ref name, including the first character;
7373
// leading underscores are a common convention for release/internal branches (e.g.
7474
// "_release/v1.2.3"), which previously failed validation as a PR's base branch.
75+
// Parentheses are valid per git-check-ref-format and commonly appear in branch names that
76+
// use Conventional Commit-style scopes (e.g. "feat(parser)-handle-empty-input").
7577
// All git calls use execFileSync (not shell interpolation), so none of these characters carry injection risk.
76-
const validPattern = /^[a-zA-Z0-9@_][a-zA-Z0-9/_.#+,@-]*$/;
78+
const validPattern = /^[a-zA-Z0-9@_][a-zA-Z0-9/_.#+,@()-]*$/;
7779

7880
if (!validPattern.test(branchName)) {
7981
throw new Error(
80-
`Invalid branch name: "${branchName}". Branch names must start with an alphanumeric character, underscore, or '@' and contain only alphanumeric characters, forward slashes, hyphens, underscores, periods, hashes (#), plus signs (+), commas (,), or at signs (@).`,
82+
`Invalid branch name: "${branchName}". Branch names must start with an alphanumeric character, underscore, or '@' and contain only alphanumeric characters, forward slashes, hyphens, underscores, periods, hashes (#), plus signs (+), commas (,), at signs (@), or parentheses.`,
8183
);
8284
}
8385

‎test/validate-branch-name.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ describe("validateBranchName", () => {
2929
expect(() => validateBranchName("release.1.2.3")).not.toThrow();
3030
});
3131

32+
it("should accept branch names containing parentheses", () => {
33+
expect(() =>
34+
validateBranchName("feat(example)-valid-branch"),
35+
).not.toThrow();
36+
expect(() =>
37+
validateBranchName("fix(parser)-handle-empty-input"),
38+
).not.toThrow();
39+
});
40+
3241
it("should accept typical branch name formats", () => {
3342
expect(() =>
3443
validateBranchName("claude/issue-123-20250101-1234"),

0 commit comments

Comments
 (0)