From 3729b5c0749c7820b52ab3b177c0720adc5f075b Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 28 Jun 2026 15:25:58 +0200 Subject: [PATCH] improve github webhook --- app/Http/Controllers/Webhook/Github.php | 10 +++++++ tests/Feature/Webhook/WebhookHmacTest.php | 33 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/app/Http/Controllers/Webhook/Github.php b/app/Http/Controllers/Webhook/Github.php index c9b0116fb..28e92dcd4 100644 --- a/app/Http/Controllers/Webhook/Github.php +++ b/app/Http/Controllers/Webhook/Github.php @@ -261,6 +261,16 @@ public function normal(Request $request) return response('Nothing to do. No GitHub App found.'); } $webhook_secret = data_get($github_app, 'webhook_secret'); + if (empty($webhook_secret)) { + auditLogWebhookFailure('github', 'webhook_secret_missing', [ + 'mode' => 'app', + 'github_app_id' => $github_app->id, + 'github_app_name' => $github_app->name, + 'installation_target_id' => $x_github_hook_installation_target_id, + ]); + + return response('Invalid signature.'); + } $hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret); if (config('app.env') !== 'local') { if (! hash_equals($x_hub_signature_256, $hmac)) { diff --git a/tests/Feature/Webhook/WebhookHmacTest.php b/tests/Feature/Webhook/WebhookHmacTest.php index 3f49ff43d..011b36731 100644 --- a/tests/Feature/Webhook/WebhookHmacTest.php +++ b/tests/Feature/Webhook/WebhookHmacTest.php @@ -2,6 +2,7 @@ use App\Models\Application; use App\Models\Environment; +use App\Models\GithubApp; use App\Models\Project; use App\Models\Server; use App\Models\Team; @@ -100,6 +101,38 @@ function createApplicationWithWebhook(string $repo = 'test-org/test-repo', strin }); }); +describe('GitHub App Webhook HMAC', function () { + test('rejects push when app webhook secret is empty', function () { + $team = Team::factory()->create(); + GithubApp::create([ + 'uuid' => (string) str()->uuid(), + 'name' => 'github-app-webhook-test', + 'api_url' => 'https://api.github.com', + 'html_url' => 'https://github.com', + 'app_id' => 1234567890, + 'webhook_secret' => null, + 'team_id' => $team->id, + ]); + + $payload = json_encode([ + 'ref' => 'refs/heads/main', + 'repository' => ['id' => 987654321], + 'after' => 'abc123', + 'commits' => [], + ]); + + $response = $this->call('POST', '/webhooks/source/github/events', [], [], [], [ + 'HTTP_X-GitHub-Event' => 'push', + 'HTTP_X-GitHub-Hook-Installation-Target-Id' => '1234567890', + 'HTTP_X-Hub-Signature-256' => 'sha256='.hash_hmac('sha256', $payload, ''), + 'CONTENT_TYPE' => 'application/json', + ], $payload); + + $response->assertOk(); + expect($response->getContent())->toContain('Invalid signature'); + }); +}); + describe('GitLab Manual Webhook HMAC', function () { test('rejects push when secret is empty', function () { $app = createApplicationWithWebhook();