fix(coolify-webhook): handle unsigned payloads and underscore event names#42
Closed
finedesignz wants to merge 1 commit into
Closed
fix(coolify-webhook): handle unsigned payloads and underscore event names#42finedesignz wants to merge 1 commit into
finedesignz wants to merge 1 commit into
Conversation
Coolify's built-in webhook sender (as of 4.0.0-beta) sends unsigned POSTs with no X-Coolify-Signature/X-Coolify-Timestamp headers and uses underscore event names (deployment_failed, deployment_success) rather than dot-notation. - Make HMAC optional: skip signature check when headers absent, require valid user_id + configured secret as the guard instead - Expand Zod enum to accept both underscore and dot-notation event names - Fix isFailure check and triage dispatch to cover both event name formats Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Owner
Author
|
Superseded by the in-flight URL-token rewrite PR which folds in the event-name fix. URL-token auth replaces the HMAC-optional approach. Closing to avoid merge conflict. |
4 tasks
finedesignz
added a commit
that referenced
this pull request
May 26, 2026
…webhook ingest (#44) Coolify's webhook UI only exposes a single URL field (no headers, no signing), so the original HMAC-header design was unusable against real deployments. Replace it with a per-user token embedded in the URL path, while keeping the legacy HMAC route mounted for a 30-day grace period. Part 1 — URL-token auth - New primary route: POST /api/coolify/webhook/:user_id/:token token IS users.coolify_webhook_secret, constant-time compared. - Legacy POST /api/coolify/webhook/:user_id kept; returns Deprecation + Sunset headers and logs a warning per hit. - GET/POST /api/account/coolify-webhook-secret now returns the full URL with the token embedded. Part 2 — Test-connection UI + audit log - New table coolify_webhook_attempts (capped 100/user, app-side trim). - Every hit logged: success, auth_failed, ip_rejected, bad_payload, legacy_hmac. - GET /api/account/coolify-webhook-attempts?limit=N (JWT). - SettingsPage Coolify Webhook card renders the last 10 attempts inline with status pill + IP + reason + relative timestamp + refresh button. Part 3 — IP allowlist (defense in depth) - Optional users.coolify_webhook_allowed_ips (CSV of IPv4/IPv6/CIDR). NULL/empty = allow all (back-compat). - GET/PUT /api/account/coolify-webhook-allowed-ips (JWT, validates CIDR). - Zero-dep CIDR helper at hub/src/lib/cidr.ts (IPv4 + IPv6 + CIDR). - Rejected requests get 403 + audit row with reason 'source_ip_not_in_allowlist'. Coolify event-name fix (discovered mid-flight from PR #42 investigation) - Coolify's SendWebhookJob emits underscore event names (deployment_success, deployment_failed), not the dotted form. - Zod schema now accepts both and normalizes internally via EVENT_ALIAS. Tests - 34 new/updated tests in hub/test/{coolify-webhook,cidr}.test.ts cover URL-token success + wrong-token, no-secret enumeration safety, underscore event aliasing, IP allowlist match/mismatch/CIDR/x-forwarded-for, legacy HMAC success + Deprecation header + every failure path. - Full hub suite: 132 pass / 0 fail. - web/bun run build: green. Docs - docs/coolify-webhook-migration.md: new "2026-05-25 update" section documents URL-token auth, Coolify event-name shape, IP allowlist, legacy grace period, audit log. - CLAUDE.md: file-map entries updated to reflect new ingress shape + new endpoints + cidr helper. User action post-deploy: re-rotate via Settings → Supervisor → Coolify Webhook (the previously-pasted URL will keep working via the legacy HMAC route, but Coolify can't actually send HMAC headers, so re-rotating to get the new URL format is required for Coolify-originated webhooks to succeed). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
X-Coolify-SignatureorX-Coolify-Timestampdeployment_failed,deployment_success) not dot-notation (deployment.failed)401 missing_signatureand400 bad_payloadChanges
user_id+ configuredcoolify_webhook_secretas the gatedeployment_failed/deployment_success/deployment_in_progress(Coolify built-in) and dot-notation variants (custom senders / future Coolify)isFailurecheck covers both event name formats for triage dispatchCoolify config status
webhook_notification_settings: already configured with the correct URL,webhook_enabled=true,deployment_success=true,deployment_failure=truehttps://app.remo-code.com/api/coolify/webhook/233c6d63-5f44-43f4-9eae-efc34a00735aTest plan
202 { ok: true, run_id: ... }in Coolify webhook logsscheduled_task_runswithstatus=pending🤖 Generated with Claude Code