mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-08-03 09:48:31 +08:00
fix: allow leading underscore in branch names (valid per git-check-ref-format) (#1486)
Branch names starting with an underscore (e.g. _release/v1.2.3) are valid per git check-ref-format but were rejected by validateBranchName's first-character whitelist. Since setupBranch validates a PR's baseRefName after checkout, the action failed on every open PR targeting such a branch. A leading underscore carries no option-injection risk (only a leading dash does, which is still rejected separately). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
214a70611b
commit
5bfa96a5b0
@ -27,7 +27,7 @@ function extractFirstLabel(githubData: FetchDataResult): string | undefined {
|
|||||||
* This prevents command injection by ensuring only safe characters are used.
|
* This prevents command injection by ensuring only safe characters are used.
|
||||||
*
|
*
|
||||||
* Valid branch names:
|
* Valid branch names:
|
||||||
* - Start with alphanumeric character or @ (not dash, to prevent option injection)
|
* - Start with alphanumeric character, underscore, or @ (not dash, to prevent option injection)
|
||||||
* - Contain only alphanumeric, forward slash, hyphen, underscore, period, hash (#), plus (+), comma (,), or at sign (@)
|
* - Contain only alphanumeric, forward slash, hyphen, underscore, period, hash (#), plus (+), comma (,), or at sign (@)
|
||||||
* - Do not start or end with a period
|
* - Do not start or end with a period
|
||||||
* - Do not end with a slash
|
* - Do not end with a slash
|
||||||
@ -68,12 +68,15 @@ export function validateBranchName(branchName: string): void {
|
|||||||
// @ is valid per git-check-ref-format anywhere in a ref name, including the first character
|
// @ is valid per git-check-ref-format anywhere in a ref name, including the first character
|
||||||
// (e.g. ticket conventions like "TICKET-123@add-feature" or prefixes like "@hotfix/...");
|
// (e.g. ticket conventions like "TICKET-123@add-feature" or prefixes like "@hotfix/...");
|
||||||
// the bare name "@" (HEAD shorthand) and the "@{" sequence (reflog syntax) are rejected below.
|
// the bare name "@" (HEAD shorthand) and the "@{" sequence (reflog syntax) are rejected below.
|
||||||
|
// _ is valid per git-check-ref-format anywhere in a ref name, including the first character;
|
||||||
|
// leading underscores are a common convention for release/internal branches (e.g.
|
||||||
|
// "_release/v1.2.3"), which previously failed validation as a PR's base branch.
|
||||||
// All git calls use execFileSync (not shell interpolation), so none of these characters carry injection risk.
|
// All git calls use execFileSync (not shell interpolation), so none of these characters carry injection risk.
|
||||||
const validPattern = /^[a-zA-Z0-9@][a-zA-Z0-9/_.#+,@-]*$/;
|
const validPattern = /^[a-zA-Z0-9@_][a-zA-Z0-9/_.#+,@-]*$/;
|
||||||
|
|
||||||
if (!validPattern.test(branchName)) {
|
if (!validPattern.test(branchName)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Invalid branch name: "${branchName}". Branch names must start with an alphanumeric character or '@' and contain only alphanumeric characters, forward slashes, hyphens, underscores, periods, hashes (#), plus signs (+), commas (,), or at signs (@).`,
|
`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 (@).`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,6 +74,16 @@ describe("validateBranchName", () => {
|
|||||||
expect(() => validateBranchName("@hotfix/login-timeout")).not.toThrow();
|
expect(() => validateBranchName("@hotfix/login-timeout")).not.toThrow();
|
||||||
expect(() => validateBranchName("agent/task@abc123")).not.toThrow();
|
expect(() => validateBranchName("agent/task@abc123")).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should accept branch names starting with underscore (git-valid, common for release branches)", () => {
|
||||||
|
// Leading underscores are valid per git check-ref-format and a common
|
||||||
|
// convention for release/internal branches. Rejecting them broke the
|
||||||
|
// action on any open PR whose base branch was e.g. "_release/v1.2.3",
|
||||||
|
// since setupBranch validates the PR's baseRefName after checkout.
|
||||||
|
expect(() => validateBranchName("_release/v1.2.3")).not.toThrow();
|
||||||
|
expect(() => validateBranchName("_internal")).not.toThrow();
|
||||||
|
expect(() => validateBranchName("_wip/feature-x")).not.toThrow();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("command injection attempts", () => {
|
describe("command injection attempts", () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user