mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(webhooks): always verify manual webhook signatures
GitHub, Gitea and Bitbucket manual webhooks accepted any signature when APP_ENV=local. GitLab and the GitHub App webhook already did not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9c7f2dc412
commit
e755f4c9e0
@@ -120,7 +120,7 @@ class Bitbucket extends Controller
|
||||
}
|
||||
$hash = $parts[1];
|
||||
$payloadHash = hash_hmac('sha256', $rawPayload, $webhook_secret);
|
||||
if (! hash_equals($hash, $payloadHash) && ! isDev()) {
|
||||
if (! hash_equals($hash, $payloadHash)) {
|
||||
auditLogWebhookFailure('bitbucket', 'invalid_signature', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'application_name' => $application->name,
|
||||
|
||||
@@ -106,7 +106,7 @@ class Gitea extends Controller
|
||||
continue;
|
||||
}
|
||||
$hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret);
|
||||
if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) {
|
||||
if (! hash_equals($x_hub_signature_256, $hmac)) {
|
||||
auditLogWebhookFailure('gitea', 'invalid_signature', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'application_name' => $application->name,
|
||||
|
||||
@@ -119,7 +119,7 @@ class Github extends Controller
|
||||
continue;
|
||||
}
|
||||
$hmac = hash_hmac('sha256', $request->getContent(), $webhook_secret);
|
||||
if (! hash_equals($x_hub_signature_256, $hmac) && ! isDev()) {
|
||||
if (! hash_equals($x_hub_signature_256, $hmac)) {
|
||||
auditLogWebhookFailure('github', 'invalid_signature', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'application_name' => $application->name,
|
||||
|
||||
@@ -631,6 +631,34 @@ describe('Gitea Manual Webhook HMAC', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Manual Webhook HMAC in the local environment', function () {
|
||||
test('rejects an invalid signature when APP_ENV is local', function (string $provider) {
|
||||
config(['app.env' => 'local']);
|
||||
Queue::fake();
|
||||
$application = makeWebhookApplicationServerFunctional(createApplicationWithWebhook());
|
||||
|
||||
$response = sendManualWebhookPush($this, $provider, $application, validSignature: false);
|
||||
|
||||
$response->assertOk();
|
||||
expect($response->getContent())->toContain('Invalid signature')
|
||||
->not->toContain('Deployment queued');
|
||||
expect(ApplicationDeploymentQueue::query()->where('application_id', $application->id)->exists())->toBeFalse();
|
||||
})->with(['github', 'gitea', 'bitbucket']);
|
||||
|
||||
test('accepts a valid signature when APP_ENV is local', function (string $provider) {
|
||||
config(['app.env' => 'local']);
|
||||
Queue::fake();
|
||||
$application = makeWebhookApplicationServerFunctional(createApplicationWithWebhook());
|
||||
|
||||
$response = sendManualWebhookPush($this, $provider, $application);
|
||||
|
||||
$response->assertOk();
|
||||
expect($response->getContent())->toContain('Deployment queued')
|
||||
->not->toContain('Invalid signature');
|
||||
expect(ApplicationDeploymentQueue::query()->where('application_id', $application->id)->exists())->toBeTrue();
|
||||
})->with(['github', 'gitea', 'bitbucket']);
|
||||
});
|
||||
|
||||
describe('Manual Webhook Repository Matching', function () {
|
||||
test('github rejects empty repository without leaking applications', function () {
|
||||
$app = createApplicationWithWebhook(overrides: ['name' => 'secret-github-app']);
|
||||
|
||||
Reference in New Issue
Block a user