CVE-2026-75511 Overview
Novu, an open-source notification infrastructure platform, contains a Server-Side Request Forgery (SSRF) vulnerability [CWE-918] in versions prior to 3.18.0. The flaw resides in the chat provider pipeline, which accepts webhook URLs from subscriber credentials, channel endpoints, and event payloads without applying outbound URL safety checks. An authenticated user can supply internal or restricted destinations, causing the Novu worker to issue attacker-directed POST requests to internal network services. Affected chat providers include Slack, Discord, Mattermost, Microsoft Teams, Grafana On-Call, Ryver, Rocket.Chat, GetStream, and Zulip. The issue is fixed in Novu 3.18.0.
Critical Impact
Authenticated attackers can pivot through the Novu worker to reach internal services, trigger unintended actions, and probe restricted network segments.
Affected Products
- Novu notification platform versions prior to 3.18.0
- Chat provider integrations: Slack, Discord, Mattermost, Microsoft Teams
- Chat provider integrations: Grafana On-Call, Ryver, Rocket.Chat, GetStream, Zulip
Discovery Timeline
- 2026-09-22 - CVE-2026-75511 published to NVD
- 2026-09-22 - Last updated in NVD database
Technical Details for CVE-2026-75511
Vulnerability Analysis
Novu accepts chat webhook URLs from four attacker-influenced inputs: subscriber credentials.webhookUrl, endpoint.url, event payload.webhookUrl, and event overrides.webhookUrl. The selected endpoint.url flows through send-message-chat.usecase.ts into raw HTTP POST requests issued by each chat provider module.
The generic webhook providers in Novu apply outbound safety controls via normalizeOutboundHttpUrl, assertSafeOutboundUrl, and the DNS-pinned safeOutboundJsonRequest helpers. The chat provider code paths bypassed these controls entirely, allowing arbitrary destinations including RFC1918 private addresses, link-local ranges, and loopback interfaces.
Root Cause
The chat provider modules instantiated their own axios clients without URL validation. Each provider constructed HTTP requests directly from user-controlled input, treating the webhook URL as trusted. The absence of allow-list checks and DNS pinning enabled requests to internal services from the Novu worker context.
Attack Vector
An authenticated user with permission to manage subscribers or trigger events supplies a webhook URL pointing to an internal resource, such as http://169.254.169.254/latest/meta-data/ or http://localhost:8080/admin. When the notification is dispatched through an affected chat channel, the Novu worker issues a POST request to the specified target. The response body is not returned, but the request itself can trigger actions on internal services vulnerable to unauthenticated POST calls.
// Patch: packages/providers/src/lib/chat/discord/discord.provider.ts
ISendMessageSuccessResponse,
isChannelDataOfType,
} from '@novu/stateless';
-import axios from 'axios';
import { BaseProvider, CasingEnum } from '../../../base.provider';
+import { resolveSafeChatWebhookUrl, safeChatWebhookJsonRequest } from '../../../utils/safe-chat-webhook-request';
import { WithPassthrough } from '../../../utils/types';
export class DiscordProvider extends BaseProvider implements IChatProvider {
protected casing = CasingEnum.CAMEL_CASE;
channelType = ChannelTypeEnum.CHAT as ChannelTypeEnum.CHAT;
public id = ChatProviderIdEnum.Discord;
- private axiosInstance = axios.create();
constructor(private config) {
super();
Source: GitHub Commit dabfd66. The patch replaces the raw axios client with safeChatWebhookJsonRequest, which enforces DNS-pinned outbound URL validation consistent with the generic webhook providers.
Detection Methods for CVE-2026-75511
Indicators of Compromise
- Novu worker logs showing outbound POST requests to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) or loopback addresses.
- Requests from the Novu worker to cloud metadata endpoints such as 169.254.169.254 or metadata.google.internal.
- Subscriber records or event payloads containing webhookUrl values referencing internal hostnames or non-standard ports.
Detection Strategies
- Inspect send-message-chat.usecase.ts execution traces for destination hosts that fail to resolve to public chat provider domains.
- Correlate authenticated Novu API calls that write credentials.webhookUrl with subsequent outbound worker HTTP activity.
- Alert on any Novu-originated request whose destination hostname does not match the expected provider domain list (discord.com, slack.com, hooks.slack.com, teams.microsoft.com, and similar).
Monitoring Recommendations
- Enable egress filtering on Novu worker nodes and log all denied outbound connections.
- Capture and retain HTTP client logs from provider modules with full destination URL and response code.
- Review audit trails for subscriber and event API calls that set or override webhook URLs.
How to Mitigate CVE-2026-75511
Immediate Actions Required
- Upgrade Novu to version 3.18.0 or later where safeChatWebhookJsonRequest enforces DNS-pinned URL validation across all chat providers.
- Audit existing subscriber records and event history for webhookUrl values pointing to internal or metadata endpoints and revoke the associated credentials.
- Rotate any secrets or tokens accessible from the Novu worker network segment that may have been targeted by SSRF probes.
Patch Information
The fix is delivered in Novu 3.18.0 via commit dabfd66. Consult the GitHub Security Advisory GHSA-pg9q-8v57-hqph, Pull Request #11455, and the v3.18.0 Release Notes for full change details.
Workarounds
- Deploy the Novu worker in an isolated network segment with strict egress ACLs limiting outbound HTTP to known chat provider domains.
- Place an outbound HTTP proxy in front of the Novu worker to enforce destination allow-listing and reject requests to private, loopback, or metadata IP ranges.
- Restrict which authenticated roles can write credentials.webhookUrl, endpoint.url, payload.webhookUrl, and overrides.webhookUrl fields.
# Example egress allow-list (iptables) restricting Novu worker outbound HTTPS
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -d discord.com -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -d hooks.slack.com -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --dport 443 -d teams.microsoft.com -j ACCEPT
iptables -A OUTPUT -o eth0 -d 169.254.169.254 -j DROP
iptables -A OUTPUT -o eth0 -d 10.0.0.0/8 -j DROP
iptables -A OUTPUT -o eth0 -d 172.16.0.0/12 -j DROP
iptables -A OUTPUT -o eth0 -d 192.168.0.0/16 -j DROP
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.