Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
28 changes: 21 additions & 7 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31714,24 +31714,38 @@ async function checkForkAuthorization(octokit, context, commenter) {
};
}

// Allow repository owner to use commands on any PR (including Dependabot PRs)
// Allow repository owner, admin, or maintainer to use commands on any PR (including Dependabot PRs)
const repoOwner = context?.repo?.owner;

// First check: is this user the repo owner?
if (repoOwner && commenter.login === repoOwner) {
return {
authorized: true,
reason: 'repo_owner',
};
}

// Check collaborator permission (admin, maintain, write, or read)
// This handles the case where repo owner wasn't detected but user has admin/maintainer perms
const authResult = await checkAuthorization(octokit, context, commenter);

// If not authorized on fork PR, silent block
if (!authResult.authorized) {
// If authorized (any permission level including admin/maintainer), allow
if (authResult.authorized) {
return {
authorized: true,
reason: authResult.reason || 'collaborator',
};
}

// For fork PRs from non-collaborators, silent block per SECURITY.md
if (isFork) {
return {
authorized: false,
reason: null, // Silent block for fork PRs
reason: null, // Silent block
};
}

// For non-fork PRs, return the authorization result (will show error to user)
return authResult;
}

Expand Down Expand Up @@ -40386,7 +40400,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
guidance,
GUIDANCE_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }
);
core.info(`Posted guidance comment for error: ${errorType}`);

Expand Down Expand Up @@ -40427,7 +40441,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
getUnauthorizedMessage(),
AUTH_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }
);

if (commentId) {
Expand Down Expand Up @@ -40462,7 +40476,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
`🤖 Reviewing \`/zai ${parseResult.command}\`...\n\n${PROGRESS_MARKER}`,
PROGRESS_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }
);

core.info(`Authorized command from collaborator: ${commenter.login}`);
Expand Down
6 changes: 3 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
guidance,
GUIDANCE_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

/zai explain

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Error: Failed to get explanation

);
core.info(`Posted guidance comment for error: ${errorType}`);

Expand Down Expand Up @@ -277,7 +277,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
getUnauthorizedMessage(),
AUTH_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }
);

if (commentId) {
Expand Down Expand Up @@ -312,7 +312,7 @@ async function handleIssueCommentEvent(context, apiKey, model, owner, repo) {
pullNumber,
`🤖 Reviewing \`/zai ${parseResult.command}\`...\n\n${PROGRESS_MARKER}`,
PROGRESS_MARKER,
{ replyToId: commentId, updateExisting: false, isReviewComment: true, pullNumber }
{ replyToId: commentId, updateExisting: false, isReviewComment: false, pullNumber }
);

core.info(`Authorized command from collaborator: ${commenter.login}`);
Expand Down
22 changes: 18 additions & 4 deletions src/lib/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,24 +175,38 @@ async function checkForkAuthorization(octokit, context, commenter) {
};
}

// Allow repository owner to use commands on any PR (including Dependabot PRs)
// Allow repository owner, admin, or maintainer to use commands on any PR (including Dependabot PRs)
const repoOwner = context?.repo?.owner;

// First check: is this user the repo owner?
if (repoOwner && commenter.login === repoOwner) {
return {
authorized: true,
reason: 'repo_owner',
};
}

// Check collaborator permission (admin, maintain, write, or read)
// This handles the case where repo owner wasn't detected but user has admin/maintainer perms
const authResult = await checkAuthorization(octokit, context, commenter);

// If not authorized on fork PR, silent block
if (!authResult.authorized) {
// If authorized (any permission level including admin/maintainer), allow
if (authResult.authorized) {
return {
authorized: true,
reason: authResult.reason || 'collaborator',
};
}

// For fork PRs from non-collaborators, silent block per SECURITY.md
if (isFork) {
return {
authorized: false,
reason: null, // Silent block for fork PRs
reason: null, // Silent block
};
}

// For non-fork PRs, return the authorization result (will show error to user)
return authResult;
}

Expand Down
Loading