From 30e3e7b37097e475f2857ef7666a87fdcc0a9083 Mon Sep 17 00:00:00 2001 From: RoomWithOutRoof Date: Sat, 7 Mar 2026 02:57:02 +0800 Subject: [PATCH 1/4] fix: allow Unicode letters in branch name validation Previously, validateBranchName only allowed ASCII alphanumeric characters, rejecting valid Unicode branch names (e.g., Japanese characters). This fix uses Unicode property escapes (\p{L} for letters, \p{N} for numbers) to allow valid Unicode branch names while still blocking dangerous characters. Fixes: #1020 --- src/github/operations/branch.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/github/operations/branch.ts b/src/github/operations/branch.ts index 86197da96..6af509470 100644 --- a/src/github/operations/branch.ts +++ b/src/github/operations/branch.ts @@ -44,6 +44,7 @@ export function validateBranchName(branchName: string): void { } // Check for leading dash (prevents option injection like --help, -x) + // Allow Unicode letters (\p{L}) and numbers (\p{N}) at start if (branchName.startsWith("-")) { throw new Error( `Invalid branch name: "${branchName}". Branch names cannot start with a dash.`, @@ -58,8 +59,9 @@ export function validateBranchName(branchName: string): void { ); } - // Strict whitelist pattern: alphanumeric start, then alphanumeric/slash/hyphen/underscore/period - const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9/_.-]*$/; + // Strict whitelist pattern: alphanumeric start (including Unicode), then alphanumeric/slash/hyphen/underscore/period + // Using \p{L} for Unicode letters and \p{N} for Unicode numbers + const validPattern = /^\p{L}\p{L}*[\p{L}\p{N}/._-]*$/u; if (!validPattern.test(branchName)) { throw new Error( From f0bcd90e3f23ca77cd104d2cb1f1ef5dcf7b9fe2 Mon Sep 17 00:00:00 2001 From: RoomWithOutRoof Date: Sat, 7 Mar 2026 02:58:37 +0800 Subject: [PATCH 2/4] fix: allow # character in branch names for Azure DevOps Azure DevOps uses # for ticket linking in branch names (e.g., feature/AB#1992). This fix adds # to the allowed characters in branch name validation. Fixes: #1024 --- src/github/operations/branch.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/github/operations/branch.ts b/src/github/operations/branch.ts index 6af509470..963ba8172 100644 --- a/src/github/operations/branch.ts +++ b/src/github/operations/branch.ts @@ -59,9 +59,10 @@ export function validateBranchName(branchName: string): void { ); } - // Strict whitelist pattern: alphanumeric start (including Unicode), then alphanumeric/slash/hyphen/underscore/period - // Using \p{L} for Unicode letters and \p{N} for Unicode numbers - const validPattern = /^\p{L}\p{L}*[\p{L}\p{N}/._-]*$/u; + // Strict whitelist pattern: alphanumeric start (including Unicode), then alphanumeric/slash/hyphen/underscore/period/pound + // Using \p{L} for Unicode letters, \p{N} for Unicode numbers + // Allow # for Azure DevOps ticket linking (e.g., feature/AB#1992-sentry) + const validPattern = /^\p{L}\p{L}*[\p{L}\p{N}/._#-]*$/u; if (!validPattern.test(branchName)) { throw new Error( From b270ace9b3c1ffbc8c8f19d8e70c315ef82483c6 Mon Sep 17 00:00:00 2001 From: RoomWithOutRoof Date: Sat, 7 Mar 2026 03:00:35 +0800 Subject: [PATCH 3/4] fix: strip shell comment lines from claude_args before parsing shell-quote treats # as a comment character, causing all content after a comment line to be swallowed. This fix strips lines starting with # before passing to parseShellArgs, so users can add documentation comments to their claude_args without breaking subsequent flags. Fixes: #1019, #802 --- base-action/src/parse-sdk-options.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/base-action/src/parse-sdk-options.ts b/base-action/src/parse-sdk-options.ts index 35df281d2..706ab1c8d 100644 --- a/base-action/src/parse-sdk-options.ts +++ b/base-action/src/parse-sdk-options.ts @@ -85,14 +85,24 @@ function mergeMcpConfigs(configValues: string[]): string { * For allowedTools and disallowedTools, multiple occurrences are accumulated (null-char joined). * Accumulating flags also consume all consecutive non-flag values * (e.g., --allowed-tools "Tool1" "Tool2" "Tool3" captures all three). + * + * Note: Lines starting with # are treated as comments and stripped before parsing. + * This allows users to add documentation comments to claude_args without breaking subsequent flags. */ function parseClaudeArgsToExtraArgs( claudeArgs?: string, ): Record { if (!claudeArgs?.trim()) return {}; + // Strip comment lines (lines starting with # after trimming) + const lines = claudeArgs.split("\n"); + const nonCommentLines = lines + .map((line) => line.trim()) + .filter((line) => line && !line.startsWith("#")); + const filteredArgs = nonCommentLines.join(" "); + const result: Record = {}; - const args = parseShellArgs(claudeArgs).filter( + const args = parseShellArgs(filteredArgs).filter( (arg): arg is string => typeof arg === "string", ); From 2a229e317e9c8882e1e3e9d3db88f7b278b89961 Mon Sep 17 00:00:00 2001 From: RoomWithOutRoof Date: Sat, 7 Mar 2026 03:01:59 +0800 Subject: [PATCH 4/4] fix: allow Copilot as valid actor in permission check checkWritePermissions() calls repos.getCollaboratorPermissionLevel() with github.actor as username. When actor is Copilot (from Copilot- initiated pull_request_review), the API returns 404 because Copilot is not a regular GitHub user. This fix adds Copilot to the bypass list alongside [bot] accounts. Fixes: #1018 --- src/github/validation/permissions.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/github/validation/permissions.ts b/src/github/validation/permissions.ts index 731fcd41c..f371cfa2d 100644 --- a/src/github/validation/permissions.ts +++ b/src/github/validation/permissions.ts @@ -43,9 +43,10 @@ export async function checkWritePermissions( } } - // Check if the actor is a GitHub App (bot user) - if (actor.endsWith("[bot]")) { - core.info(`Actor is a GitHub App: ${actor}`); + // Check if the actor is a GitHub App (bot user) or known service account + // Copilot is not a regular user but has write access via GitHub App + if (actor.endsWith("[bot]") || actor === "Copilot") { + core.info(`Actor is a GitHub App or known service: ${actor}`); return true; }