Skip to content

Add URL validation for notification webhook fields#9224

Merged
andrasbacsai merged 2 commits into
nextfrom
fix/validate-notification-webhook-urls
Mar 28, 2026
Merged

Add URL validation for notification webhook fields#9224
andrasbacsai merged 2 commits into
nextfrom
fix/validate-notification-webhook-urls

Conversation

@andrasbacsai

Copy link
Copy Markdown
Member

Summary

  • Add SafeWebhookUrl validation rule for notification webhook URL fields
  • Apply validation to Slack, Discord, and custom webhook URL inputs
  • Enforce http/https scheme and block unsafe hostnames
  • Add unit tests for the new validation rule

Test plan

  • Run php artisan test --compact --filter=SafeWebhookUrl
  • Verify webhook URLs accept valid external URLs
  • Verify webhook URLs accept private network IPs (self-hosted use case)
  • Verify invalid URLs and dangerous hostnames are rejected

🤖 Generated with Claude Code

Add SafeWebhookUrl validation rule to notification webhook URL fields
(Slack, Discord, custom webhook) to enforce safe URL patterns including
scheme validation and hostname checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@andrasbacsai

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This change replaces the built-in URL validation rule with a custom SafeWebhookUrl validation rule across three Livewire notification components (Discord, Slack, and Webhook). A new SafeWebhookUrl rule class is introduced that validates webhook URLs by filtering valid URLs, restricting schemes to HTTP and HTTPS, blocking unsafe hostnames like localhost and 0.0.0.0, rejecting link-local addresses, and permitting private IP ranges for self-hosted deployments. The rule logs validation failures with context information. Unit tests verify the rule accepts valid public and private IP addresses while rejecting loopback addresses, cloud metadata IPs, internal hostnames, and non-HTTP schemes.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/validate-notification-webhook-urls

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/Livewire/Notifications/Webhook.php`:
- Around line 24-25: The Livewire property validation is insufficient because
WebhookNotificationSettings::webhook_url can be set outside Livewire; update
App\Jobs\SendWebhookJob::handle() to validate the stored webhook URL with the
same SafeWebhookUrl rule (or a shared validator/helper) immediately before
calling Http::post(), and abort/log/throw (skip sending) if validation fails;
reference WebhookNotificationSettings::webhook_url, SafeWebhookUrl and
Http::post() so you add the check in SendWebhookJob::handle() and ensure only
validated URLs are posted.

In `@app/Rules/SafeWebhookUrl.php`:
- Around line 43-93: The SafeWebhookUrl rule currently only checks the host
string and literal IPv4 in isLinkLocal/isLoopback, allowing DNS or IPv6 bypasses
(e.g., ::ffff:127.0.0.1, fe80::1, hostnames resolving to 127.0.0.0/8 or
169.254.0.0/16). Fix by resolving the hostname to A and AAAA records
(dns_get_record or gethostbynamel + DNS_AAAA) in the validation path that uses
$host (SafeWebhookUrl::validate / the block around $blockedHosts), then for each
resolved address: normalize with inet_pton and detect IPv4-mapped IPv6 addresses
(treat ::ffff:x.y.z.w as IPv4), use existing isLoopback(string $ip) and extend
it to accept normalized IPv6-mapped IPv4, and update isLinkLocal(string $ip) to
handle IPv6 link-local ranges (fe80::/10) and to check IPv4 addresses by numeric
mask (169.254.0.0/16) using ip2long bitmasking; reject the URL if any resolved
address matches loopback or link-local rules and log via Log::warning as done
now.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 153b697d-5b26-4af5-aea2-d9a6ff1b3768

📥 Commits

Reviewing files that changed from the base of the PR and between 98569e4 and 564cd83.

📒 Files selected for processing (5)
  • app/Livewire/Notifications/Discord.php
  • app/Livewire/Notifications/Slack.php
  • app/Livewire/Notifications/Webhook.php
  • app/Rules/SafeWebhookUrl.php
  • tests/Unit/SafeWebhookUrlTest.php

Comment thread app/Livewire/Notifications/Webhook.php
Comment thread app/Rules/SafeWebhookUrl.php
Prevent server-side request forgery (SSRF) attacks by validating webhook URLs before sending requests. Blocks loopback addresses, cloud metadata endpoints, and localhost URLs.

- Add SafeWebhookUrl rule validation in SendWebhookJob.handle()
- Log warning when unsafe URLs are rejected
- Add comprehensive unit tests covering valid and invalid URL scenarios
@andrasbacsai andrasbacsai merged commit 377ce24 into next Mar 28, 2026
4 checks passed
@andrasbacsai andrasbacsai deleted the fix/validate-notification-webhook-urls branch March 28, 2026 13:39
@andrasbacsai andrasbacsai mentioned this pull request Apr 5, 2026
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Apr 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant