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", ); diff --git a/src/github/operations/branch.ts b/src/github/operations/branch.ts index 86197da96..963ba8172 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,10 @@ 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/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( 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; }