mastra-ai/mastra · error
Push notification URL must not target local or internal host
Error message
Push notification URL must not target local or internal hosts: ${hostname} What it means
Even without an allowlist, the sender hard-blocks push notification URLs whose hostname is a well-known local/internal name (e.g. localhost, *.local, metadata endpoints, *.internal) via isDisallowedHostname. This prevents SSRF into loopback or cloud-internal services.
Source
Thrown at packages/server/src/server/a2a/push-notification-sender.ts:91
getStore() {
return this.pushNotificationStore;
}
private async resolveValidatedDestination(rawUrl: string) {
const url = new URL(rawUrl);
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
throw new Error(`Push notification URL must use http or https: ${url.protocol}`);
}
const hostname = url.hostname.toLowerCase();
if (this.options.allowedHosts && !this.options.allowedHosts.includes(hostname)) {
throw new Error(`Push notification host is not allowed: ${hostname}`);
}
if (isDisallowedHostname(hostname)) {
throw new Error(`Push notification URL must not target local or internal hosts: ${hostname}`);
}
if (isDisallowedIpAddress(hostname)) {
throw new Error(`Push notification URL must not target local or private IPs: ${hostname}`);
}
const resolvedAddresses =
isIP(hostname) === 0
? await (this.options.lookup ?? defaultLookup)(hostname, { all: true, verbatim: true })
: [{ address: hostname, family: isIP(hostname) }];
if (resolvedAddresses.some(result => isDisallowedIpAddress(result.address))) {
throw new Error(`Push notification URL resolved to a local or private IP: ${hostname}`);
}
const requestUrl = new URL(url.toString());
requestUrl.hostname = resolvedAddresses[0]!.address;
View on GitHub (pinned to 75dd419e61)
Solutions
- Use a publicly resolvable hostname for the push notification endpoint
- For local development, expose the endpoint via a tunnel (ngrok/smee) or a machine's LAN IP if isDisallowedIpAddress permits it
- If this is a legitimate internal host, host the receiver externally or relax the sender's hostname blocklist via supported options
Example fix
// before url: 'http://localhost:4111/a2a/push' // after url: 'https://dev-tunnel.example.com/a2a/push'
Defensive patterns
Strategy: validation
Validate before calling
const LOCAL_HOST_RE = /(^|\.)(local|internal|localhost)$/i;
function assertPublicHost(raw: string) {
const host = new URL(raw).hostname.toLowerCase();
if (host === 'localhost' || LOCAL_HOST_RE.test(host)) {
throw new Error(`Host ${host} is local/internal`);
}
} Type guard
const isPublicHostname = (raw: string): boolean => {
const h = new URL(raw).hostname.toLowerCase();
return h !== 'localhost' && !/\.(local|internal)$/i.test(h);
}; Try / catch
try {
await sender.sendNotifications(task, configs);
} catch (err) {
if (err instanceof Error && err.message.includes('must not target local or internal hosts')) {
logger.warn('Internal push target rejected', { err: err.message });
} else throw err;
} Prevention
- Never register localhost or internal service names as push endpoints in shared environments
- Use public tunnels for local development
- Document that docker-compose service names will be blocked
When it happens
Trigger: Registering a push notification URL whose hostname resolves to a disallowed name such as 'localhost', 'localhost.localdomain', 'metadata.google.internal', or any '*.[internal/local]' style host.
Common situations: Developers pointing push webhooks at a locally running test server (localhost:4111), Docker-compose service names like 'http://backend:3000', or accidentally registering an internal-only callback host in production config.
Related errors
- Push notification URL must not target local or private IPs:
- URL resolves to a private or reserved address.
- Push notification URL must use http or https: ${url.protocol
- Push notification host is not allowed: ${hostname}
- Push notification URL resolved to a local or private IP: ${h
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/27c9c32a3f236b51.
Report an issue: GitHub.