mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
* feat: skip permission check for GitHub App bot users GitHub Apps (users ending with [bot]) now bypass permission checks as they have their own authorization mechanism. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add allow_bot_users option to control bot user access - Add allow_bot_users input parameter (default: false) - Modify checkHumanActor to optionally allow bot users - Add comprehensive tests for bot user handling - Improve security by blocking bot users by default This change prevents potential prompt injection attacks from bot users while providing flexibility for trusted bot integrations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: mark bot user support feature as completed in roadmap 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: move allowedBots parameter to context object Move allowedBots from function parameter to context.inputs to maintain consistency with other input handling throughout the codebase. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: update README for bot user support feature Add documentation for the new allowed_bots parameter that enables bot users to trigger Claude actions with granular control. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add missing allowedBots property in permissions test 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: update bot name format to include [bot] suffix in tests and docs - Update test cases to use correct bot actor names with [bot] suffix - Update documentation example to show correct bot name format - Align with GitHub's actual bot naming convention 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: normalize bot names for allowed_bots validation - Strip [bot] suffix from both actor names and allowed bot list for comparison - Allow both "dependabot" and "dependabot[bot]" formats in allowed_bots input - Display normalized bot names in error messages for consistency - Add comprehensive test coverage for both naming formats 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
97 lines
3.2 KiB
TypeScript
97 lines
3.2 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
import { describe, test, expect } from "bun:test";
|
|
import { checkHumanActor } from "../src/github/validation/actor";
|
|
import type { Octokit } from "@octokit/rest";
|
|
import { createMockContext } from "./mockContext";
|
|
|
|
function createMockOctokit(userType: string): Octokit {
|
|
return {
|
|
users: {
|
|
getByUsername: async () => ({
|
|
data: {
|
|
type: userType,
|
|
},
|
|
}),
|
|
},
|
|
} as unknown as Octokit;
|
|
}
|
|
|
|
describe("checkHumanActor", () => {
|
|
test("should pass for human actor", async () => {
|
|
const mockOctokit = createMockOctokit("User");
|
|
const context = createMockContext();
|
|
context.actor = "human-user";
|
|
|
|
await expect(
|
|
checkHumanActor(mockOctokit, context),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
test("should throw error for bot actor when not allowed", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "test-bot[bot]";
|
|
context.inputs.allowedBots = "";
|
|
|
|
await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow(
|
|
"Workflow initiated by non-human actor: test-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.",
|
|
);
|
|
});
|
|
|
|
test("should pass for bot actor when all bots allowed", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "test-bot[bot]";
|
|
context.inputs.allowedBots = "*";
|
|
|
|
await expect(
|
|
checkHumanActor(mockOctokit, context),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
test("should pass for specific bot when in allowed list", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "dependabot[bot]";
|
|
context.inputs.allowedBots = "dependabot[bot],renovate[bot]";
|
|
|
|
await expect(
|
|
checkHumanActor(mockOctokit, context),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
test("should pass for specific bot when in allowed list (without [bot])", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "dependabot[bot]";
|
|
context.inputs.allowedBots = "dependabot,renovate";
|
|
|
|
await expect(
|
|
checkHumanActor(mockOctokit, context),
|
|
).resolves.toBeUndefined();
|
|
});
|
|
|
|
test("should throw error for bot not in allowed list", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "other-bot[bot]";
|
|
context.inputs.allowedBots = "dependabot[bot],renovate[bot]";
|
|
|
|
await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow(
|
|
"Workflow initiated by non-human actor: other-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.",
|
|
);
|
|
});
|
|
|
|
test("should throw error for bot not in allowed list (without [bot])", async () => {
|
|
const mockOctokit = createMockOctokit("Bot");
|
|
const context = createMockContext();
|
|
context.actor = "other-bot[bot]";
|
|
context.inputs.allowedBots = "dependabot,renovate";
|
|
|
|
await expect(checkHumanActor(mockOctokit, context)).rejects.toThrow(
|
|
"Workflow initiated by non-human actor: other-bot (type: Bot). Add bot to allowed_bots list or use '*' to allow all bots.",
|
|
);
|
|
});
|
|
});
|