Verified. When creating or updating an API webhook, /api/v1/webhooks only validates target_url as a syntactically valid URL. It does not block loopback addresses, private IP ranges, internal DNS names, link-local addresses, or cloud metadata endpoints. The webhook can then be triggered through /api/v1/webhooks/{webhook}/retry, causing the Invoice Ninja backend server to issue a request to the attacker-controlled URL.
This is a high-severity candidate in a multi-tenant hosted environment, or in deployments where the application server can reach internal management services. In a single-tenant self-hosted deployment where only the instance administrator can create webhooks, the impact should be downgraded to medium or treated as a hardening issue.
The request is sent from the Invoice Ninja application server, not from the attacker's machine. Therefore, reachable targets are based on the server-side network position, for example:
127.0.0.1 / loopback services on the application host or container169.254.169.254, depending on cloud and egress controlsThe issue is a blind SSRF: the full response body is not directly returned to the attacker. It is still useful for internal network probing and for triggering internal HTTP endpoints.
POST /api/v1/webhooksPUT /api/v1/webhooks/{webhook}