From a692ff096c1b305ca590702feb0dc26749d449d6 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 30 May 2025 12:57:34 -0500 Subject: [PATCH] fix: support both classic and fine-grained GitHub tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update token validation to support github_pat_ tokens in addition to ghp_ tokens - Add trust proxy configuration for reverse proxy deployments - Update port configuration from 3002 to 3003 in docker-compose - Add request body validation in webhook controller - Ensure consistent token pattern handling across services 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .env.example | 5 +++++ docker-compose.yml | 7 ++++--- src/controllers/githubController.ts | 6 ++++++ src/index.ts | 8 ++++++++ src/services/claudeService.ts | 4 +++- src/services/githubService.ts | 3 ++- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index b8979d7..dff96d3 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,11 @@ NODE_ENV=development PORT=3002 +# Trust Proxy Configuration +# Set to 'true' when running behind reverse proxies (nginx, cloudflare, etc.) +# This allows proper handling of X-Forwarded-For headers for rate limiting +TRUST_PROXY=false + # ============================ # SECRETS CONFIGURATION # ============================ diff --git a/docker-compose.yml b/docker-compose.yml index 323c425..c176bfe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ services: webhook: build: . ports: - - "8082:3002" + - "8082:3003" volumes: - .:/app - /app/node_modules @@ -11,7 +11,8 @@ services: - ${HOME}/.claude:/home/claudeuser/.claude environment: - NODE_ENV=production - - PORT=3002 + - PORT=3003 + - TRUST_PROXY=${TRUST_PROXY:-true} - AUTHORIZED_USERS=${AUTHORIZED_USERS:-Cheffromspace} - BOT_USERNAME=${BOT_USERNAME:-@MCPClaude} - DEFAULT_GITHUB_OWNER=${DEFAULT_GITHUB_OWNER:-Cheffromspace} @@ -31,7 +32,7 @@ services: - GITHUB_WEBHOOK_SECRET=${GITHUB_WEBHOOK_SECRET} restart: unless-stopped healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3002/health"] + test: ["CMD", "curl", "-f", "http://localhost:3003/health"] interval: 30s timeout: 10s retries: 3 diff --git a/src/controllers/githubController.ts b/src/controllers/githubController.ts index cae4d0d..d7873e7 100644 --- a/src/controllers/githubController.ts +++ b/src/controllers/githubController.ts @@ -114,6 +114,12 @@ export const handleWebhook: WebhookHandler = async (req, res) => { const event = req.headers['x-github-event'] as string; const delivery = req.headers['x-github-delivery'] as string; + // Check if request body exists + if (!req.body) { + logger.error('Webhook request missing body'); + return res.status(400).json({ error: 'Missing request body' }); + } + // Log webhook receipt with key details (sanitize user input to prevent log injection) logger.info( { diff --git a/src/index.ts b/src/index.ts index f7002db..6a96beb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,6 +15,14 @@ import type { import { execSync } from 'child_process'; const app = express(); + +// Configure trust proxy setting based on environment +// Set TRUST_PROXY=true when running behind reverse proxies (nginx, cloudflare, etc.) +const trustProxy = process.env['TRUST_PROXY'] === 'true'; +if (trustProxy) { + app.set('trust proxy', true); +} + const PORT = parseInt(process.env['PORT'] ?? '3003', 10); const appLogger = createLogger('app'); const startupMetrics = new StartupMetrics(); diff --git a/src/services/claudeService.ts b/src/services/claudeService.ts index 8ff0f85..c65deaa 100644 --- a/src/services/claudeService.ts +++ b/src/services/claudeService.ts @@ -55,7 +55,9 @@ export async function processCommand({ const githubToken = secureCredentials.get('GITHUB_TOKEN'); // In test mode, skip execution and return a mock response - if (process.env['NODE_ENV'] === 'test' || !githubToken?.includes('ghp_')) { + // Support both classic (ghp_) and fine-grained (github_pat_) GitHub tokens + const isValidGitHubToken = githubToken && (githubToken.includes('ghp_') || githubToken.includes('github_pat_')); + if (process.env['NODE_ENV'] === 'test' || !isValidGitHubToken) { logger.info( { repo: repoFullName, diff --git a/src/services/githubService.ts b/src/services/githubService.ts index e8fcc6c..09cb4bb 100644 --- a/src/services/githubService.ts +++ b/src/services/githubService.ts @@ -24,7 +24,8 @@ let octokit: Octokit | null = null; function getOctokit(): Octokit | null { if (!octokit) { const githubToken = secureCredentials.get('GITHUB_TOKEN'); - if (githubToken?.includes('ghp_')) { + // Support both classic (ghp_) and fine-grained (github_pat_) GitHub tokens + if (githubToken && (githubToken.includes('ghp_') || githubToken.includes('github_pat_'))) { octokit = new Octokit({ auth: githubToken, userAgent: 'Claude-GitHub-Webhook'