mirror of
https://github.com/anthropics/claude-code-action.git
synced 2026-01-22 22:44:13 +08:00
Fix MCP tool availability and shell escaping in tag mode
Pass MCP config and allowed tools through claude_args to ensure tools like mcp__github_comment__update_claude_comment are properly available to Claude CLI. Key changes: - Tag mode outputs claude_args with MCP config (as JSON string) and allowed tools - Fixed shell escaping vulnerability when JSON contains single quotes - Agent mode passes through user-provided claude_args unchanged - Re-added mcp_config input for users to provide custom MCP servers - Cleaned up misleading comments and unused file operations - Clarified test workflow is for fork testing Security fix: Properly escape single quotes in MCP config JSON to prevent shell injection vulnerabilities. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
38
.github/workflows/claude-test.yml
vendored
Normal file
38
.github/workflows/claude-test.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Test workflow for km-anthropic fork (v1-dev branch)
|
||||||
|
# This tests the fork implementation, not the main repo
|
||||||
|
name: Claude Code (Fork Test)
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
pull_request_review_comment:
|
||||||
|
types: [created]
|
||||||
|
issues:
|
||||||
|
types: [opened, assigned]
|
||||||
|
pull_request_review:
|
||||||
|
types: [submitted]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
claude:
|
||||||
|
if: |
|
||||||
|
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||||
|
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||||
|
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||||
|
(github.event_name == 'issues' && (
|
||||||
|
contains(github.event.issue.body, '@claude') ||
|
||||||
|
contains(github.event.issue.title, '@claude')
|
||||||
|
))
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
issues: write
|
||||||
|
id-token: write # Required for OIDC token exchange
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Run Claude Code
|
||||||
|
uses: km-anthropic/claude-code-action@v1-dev
|
||||||
|
with:
|
||||||
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
@@ -65,6 +65,10 @@ inputs:
|
|||||||
description: "Additional arguments to pass directly to Claude CLI"
|
description: "Additional arguments to pass directly to Claude CLI"
|
||||||
required: false
|
required: false
|
||||||
default: ""
|
default: ""
|
||||||
|
mcp_config:
|
||||||
|
description: "Additional MCP configuration (JSON string) that merges with built-in GitHub MCP servers"
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
additional_permissions:
|
additional_permissions:
|
||||||
description: "Additional GitHub permissions to request (e.g., 'actions: read')"
|
description: "Additional GitHub permissions to request (e.g., 'actions: read')"
|
||||||
required: false
|
required: false
|
||||||
@@ -124,6 +128,8 @@ runs:
|
|||||||
DEFAULT_WORKFLOW_TOKEN: ${{ github.token }}
|
DEFAULT_WORKFLOW_TOKEN: ${{ github.token }}
|
||||||
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
USE_COMMIT_SIGNING: ${{ inputs.use_commit_signing }}
|
||||||
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
ADDITIONAL_PERMISSIONS: ${{ inputs.additional_permissions }}
|
||||||
|
CLAUDE_ARGS: ${{ inputs.claude_args }}
|
||||||
|
MCP_CONFIG: ${{ inputs.mcp_config }}
|
||||||
|
|
||||||
- name: Install Base Action Dependencies
|
- name: Install Base Action Dependencies
|
||||||
if: steps.prepare.outputs.contains_trigger == 'true'
|
if: steps.prepare.outputs.contains_trigger == 'true'
|
||||||
@@ -160,7 +166,7 @@ runs:
|
|||||||
INPUT_PROMPT_FILE: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
|
INPUT_PROMPT_FILE: ${{ runner.temp }}/claude-prompts/claude-prompt.txt
|
||||||
INPUT_SETTINGS: ${{ inputs.settings }}
|
INPUT_SETTINGS: ${{ inputs.settings }}
|
||||||
INPUT_TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
|
INPUT_TIMEOUT_MINUTES: ${{ inputs.timeout_minutes }}
|
||||||
INPUT_CLAUDE_ARGS: ${{ steps.prepare.outputs.mcp_config_file && format('--mcp-config {0} {1}', steps.prepare.outputs.mcp_config_file, inputs.claude_args) || inputs.claude_args }}
|
INPUT_CLAUDE_ARGS: ${{ steps.prepare.outputs.claude_args }}
|
||||||
INPUT_EXPERIMENTAL_SLASH_COMMANDS_DIR: ${{ github.action_path }}/slash-commands
|
INPUT_EXPERIMENTAL_SLASH_COMMANDS_DIR: ${{ github.action_path }}/slash-commands
|
||||||
|
|
||||||
# Model configuration
|
# Model configuration
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import { writeFile } from "fs/promises";
|
|
||||||
import { setupGitHubToken } from "../github/token";
|
import { setupGitHubToken } from "../github/token";
|
||||||
import { checkWritePermissions } from "../github/validation/permissions";
|
import { checkWritePermissions } from "../github/validation/permissions";
|
||||||
import { createOctokit } from "../github/api/client";
|
import { createOctokit } from "../github/api/client";
|
||||||
@@ -58,11 +57,7 @@ async function run() {
|
|||||||
githubToken,
|
githubToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Write MCP config to a file and set the file path as output
|
// MCP config is handled by individual modes (tag/agent) and included in their claude_args output
|
||||||
const mcpConfigPath = `${process.env.RUNNER_TEMP}/claude-mcp-config.json`;
|
|
||||||
await writeFile(mcpConfigPath, result.mcpConfig);
|
|
||||||
core.setOutput("mcp_config", result.mcpConfig);
|
|
||||||
core.setOutput("mcp_config_file", mcpConfigPath);
|
|
||||||
|
|
||||||
// Step 6: Get system prompt from mode if available
|
// Step 6: Get system prompt from mode if available
|
||||||
if (mode.getSystemPrompt) {
|
if (mode.getSystemPrompt) {
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ export const agentMode: Mode = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core.setOutput("mcp_config", JSON.stringify(mcpConfig));
|
// Agent mode: pass through user's claude_args without modification
|
||||||
|
const userClaudeArgs = process.env.CLAUDE_ARGS || "";
|
||||||
|
core.setOutput("claude_args", userClaudeArgs);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
commentId: undefined,
|
commentId: undefined,
|
||||||
|
|||||||
@@ -114,7 +114,53 @@ export const tagMode: Mode = {
|
|||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
|
|
||||||
core.setOutput("mcp_config", mcpConfig);
|
// Don't output mcp_config separately anymore - include in claude_args
|
||||||
|
|
||||||
|
// Build claude_args for tag mode with required tools
|
||||||
|
// Tag mode REQUIRES these tools to function properly
|
||||||
|
const tagModeTools = [
|
||||||
|
"Edit",
|
||||||
|
"MultiEdit",
|
||||||
|
"Glob",
|
||||||
|
"Grep",
|
||||||
|
"LS",
|
||||||
|
"Read",
|
||||||
|
"Write",
|
||||||
|
"mcp__github_comment__update_claude_comment",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add git commands when not using commit signing
|
||||||
|
if (!context.inputs.useCommitSigning) {
|
||||||
|
tagModeTools.push(
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)",
|
||||||
|
"Bash(git push:*)",
|
||||||
|
"Bash(git status:*)",
|
||||||
|
"Bash(git diff:*)",
|
||||||
|
"Bash(git log:*)",
|
||||||
|
"Bash(git rm:*)"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// When using commit signing, use MCP file ops tools
|
||||||
|
tagModeTools.push(
|
||||||
|
"mcp__github_file_ops__commit_files",
|
||||||
|
"mcp__github_file_ops__delete_files"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const userClaudeArgs = process.env.CLAUDE_ARGS || "";
|
||||||
|
|
||||||
|
// Build complete claude_args with MCP config (as JSON string), tools, and user args
|
||||||
|
// Note: Once Claude supports multiple --mcp-config flags, we can pass as file path
|
||||||
|
// Escape single quotes in JSON to prevent shell injection
|
||||||
|
const escapedMcpConfig = mcpConfig.replace(/'/g, "'\\''");
|
||||||
|
let claudeArgs = `--mcp-config '${escapedMcpConfig}' `;
|
||||||
|
claudeArgs += `--allowedTools "${tagModeTools.join(',')}" `;
|
||||||
|
if (userClaudeArgs) {
|
||||||
|
claudeArgs += userClaudeArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.setOutput("claude_args", claudeArgs.trim());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
commentId,
|
commentId,
|
||||||
|
|||||||
Reference in New Issue
Block a user