Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion base-action/src/parse-sdk-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string | null> {
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<string, string | null> = {};
const args = parseShellArgs(claudeArgs).filter(
const args = parseShellArgs(filteredArgs).filter(
(arg): arg is string => typeof arg === "string",
);

Expand Down
7 changes: 5 additions & 2 deletions src/github/operations/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.`,
Expand All @@ -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(
Expand Down
7 changes: 4 additions & 3 deletions src/github/validation/permissions.ts
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down