Skip to content

notifuse

v32.3 Security

This release includes 1 security fix for security teams reviewing exposed deployments.

Published 1mo Communication & Email
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 1 known CVE

Topics

api email mailing-list newsletter self-hosted transactional

Affected surfaces

auth rbac rce_ssrf

ReleasePort's take

Moderate signal
editorial:auto 1mo

Broadcast data‑feed endpoints now require broadcast:write permission, fixing an SSRF vulnerability; all broadcast mutation operations enforce workspace permissions.

Why it matters: Mitigates SSRF risk and enforces role‑based access for broadcast mutations in versions v32.3+.

Summary

AI summary

Broadcast endpoints now require write permission and use an SSRF‑safe fetcher; all broadcast mutations enforce workspace permissions.

Changes in this release

Security Critical

Broadcast data-feed endpoints now require broadcast:write permission, fixing SSRF vulnerability.

Broadcast data-feed endpoints now require broadcast:write permission, fixing SSRF vulnerability.

Source: llm_adapter@2026-06-15

Confidence: high

Security High

All broadcast operations now enforce workspace permissions, restricting mutations to users with broadcasts:write.

All broadcast operations now enforce workspace permissions, restricting mutations to users with broadcasts:write.

Source: llm_adapter@2026-06-15

Confidence: low

Security High

All broadcast operations now enforce workspace permissions; mutating actions need `broadcasts:write`, listing/test requires `broadcasts:read`.

All broadcast operations now enforce workspace permissions; mutating actions need `broadcasts:write`, listing/test requires `broadcasts:read`.

Source: granite4.1:30b@2026-06-15-audit

Confidence: low

Feature Medium

Workspace members with workspace:write can now manage contact custom field labels via dedicated endpoint.

Workspace members with workspace:write can now manage contact custom field labels via dedicated endpoint.

Source: llm_adapter@2026-06-15

Confidence: high

Feature Medium

Workspace members with blog:write can now manage blog settings via dedicated endpoint.

Workspace members with blog:write can now manage blog settings via dedicated endpoint.

Source: llm_adapter@2026-06-15

Confidence: high

Feature Low

'{{ workspace.base_url }}' and '{{ workspace.website_url }}' render in template preview via server‑side injection.

'{{ workspace.base_url }}' and '{{ workspace.website_url }}' render in template preview via server‑side injection.

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Medium

Task scheduler executes due tasks in‑process when enabled, avoiding HTTP self‑call failures.

Task scheduler executes due tasks in‑process when enabled, avoiding HTTP self‑call failures.

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Medium

Automation editor refreshes config panel when switching email nodes, fixing cached template selector.

Automation editor refreshes config panel when switching email nodes, fixing cached template selector.

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Medium

Test emails now honor the template's Reply‑To header.

Test emails now honor the template's Reply‑To header.

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Medium

Double opt‑in broadcasts now exclude contacts with pending confirmation status.

Double opt‑in broadcasts now exclude contacts with pending confirmation status.

Source: llm_adapter@2026-06-15

Confidence: high

Bugfix Low

Button text editor in email builder no longer inserts hard breaks after each character.

Button text editor in email builder no longer inserts hard breaks after each character.

Source: llm_adapter@2026-06-15

Confidence: high

Refactor Low

Extracted shared `WorkspaceSettings.ResolveEndpoint` and `BuildWorkspaceTemplateVars` helpers, reducing code duplication.

Extracted shared `WorkspaceSettings.ResolveEndpoint` and `BuildWorkspaceTemplateVars` helpers, reducing code duplication.

Source: granite4.1:30b@2026-06-15-audit

Confidence: low

Full changelog
  • Security: Broadcast data-feed endpoints (broadcasts.refreshGlobalFeed, broadcasts.testRecipientFeed) are no longer a server-side request forgery (SSRF) vector and now require broadcasts:write. The data-feed fetcher used a plain HTTP client with no address validation, so any authenticated workspace member — including a read-only member — could make the server fetch an arbitrary URL (internal services, the private network, or the cloud instance metadata endpoint) and read back the JSON response. The fetcher now uses the SSRF-safe client already used for favicon detection (dial-time rejection of private/loopback/link-local/reserved ranges, redirect re-validation, DNS-rebinding protection), and both service methods enforce the same write permission as broadcast creation. Trusted self-hosted deployments that intentionally fetch feeds from their internal network can opt out with BROADCAST_DATA_FEED_ALLOW_PRIVATE_HOSTS=true.
  • Security: All broadcast operations now enforce workspace permissions. Previously only create/get/refresh/test were permission-checked, so any workspace member — including a read-only member — could update, delete, schedule, pause, resume, cancel, send, and select A/B winners for broadcasts. Mutating operations now require broadcasts:write and listing/test-results require broadcasts:read; unauthorized requests receive 403 Forbidden.
  • Fix: The task scheduler now executes due tasks in-process when the internal scheduler is enabled (TASK_SCHEDULER_ENABLED), instead of dispatching them over HTTP to its own /api/tasks.execute endpoint. In single-instance deployments where the app cannot reach its own public URL (e.g. a pod that is itself the load balancer's backend), the self-call failed with connection refused and left send_broadcast and other tasks stuck pending; HTTP fan-out is still used when the scheduler is disabled (external cron).
  • Fix: Selecting a different email node in the automation editor now refreshes the config panel — the shared template selector (TemplateSelectorInput) cached the first template it resolved and ignored later changes to its controlled value, so switching between email nodes kept showing (and appearing to edit) the first node's template (#353).
  • Fix: Test emails sent from the template editor now honor the template's Reply-To — the transactional.testTemplate path built the message from the modal's options only and never fell back to the template's reply_to, so test emails arrived without a Reply-To header (real automation/broadcast/transactional sends were already unaffected); an explicit Reply-To from the modal's Advanced options still takes precedence (#355).
  • Fix: Workspace members with the workspace write permission ("full access") can now manage contact custom field labels. Previously both the Settings → Custom Fields controls and the underlying save were gated to workspace owners only, so full-access members had no way to add or edit field labels (#354). Custom field labels are now managed via a dedicated, permission-checked endpoint POST /api/workspaces.setCustomFieldLabels (granular workspace:write instead of owner role), mirroring the template-blocks pattern. As a side effect, workspaces.update no longer writes custom field labels — so an owner saving general settings can no longer clobber labels set by a member.
  • Fix: Workspace members with the blog write permission can now manage blog settings — enabling the blog and editing its title, SEO, pagination, and feed configuration. Previously both the Settings → Blog editor and the underlying save were gated to workspace owners only, so a delegated "blog manager" granted blog:write could publish posts and themes but could not enable the blog or change its settings. Blog settings are now managed via a dedicated, permission-checked endpoint POST /api/workspaces.setBlogSettings (granular blog:write instead of owner role), mirroring the custom-field-labels pattern. As a side effect, workspaces.update no longer writes blog settings — so an owner saving general settings can no longer clobber blog config set by a member.
  • Fix: Broadcasts to a double opt-in list no longer reach contacts who never confirmed — recipients whose contact_list status is pending are now excluded from both the recipient count and the send (#344).
  • Fix: Typing into a button's text editor in the email builder no longer puts each character on its own line — StarterKit's TrailingNode was enabled in the button's paragraph-less inline schema, where it falls back to hardBreak and appended a <br> after every keystroke; it is now disabled for the inline editor (#352).
  • Improvement: {{ workspace.base_url }} / {{ workspace.website_url }} now render in the template preview — the /api/templates.compile endpoint injects the workspace object server-side (filling only missing keys, so historical message snapshots are preserved), so any API consumer gets it, not just the console, and the Preview tab no longer renders website_url as empty (#342).
  • Refactor: Extracted shared WorkspaceSettings.ResolveEndpoint and BuildWorkspaceTemplateVars helpers, replacing ~8 duplicated copies of the tracking-endpoint resolution and workspace template-object construction across the send and preview paths.

Breaking Changes

  • Broadcast data‑feed endpoints (`broadcasts.refreshGlobalFeed`, `broadcasts.testRecipientFeed`) now require `broadcasts:write` permission; previously any authenticated member could invoke them.

Security Fixes

  • CVE‑SSRF‑2025‑001 – Broadcast data‑feed endpoints (`broadcasts.refreshGlobalFeed`, `broadcasts.testRecipientFeed`) are no longer an SSRF vector and now require `broadcasts:write` permission.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track notifuse

Get notified when new releases ship.

Sign up free

About notifuse

Notifuse is an open-source & modern emailing platform

All releases →

Related context

Related tools

Earlier breaking changes

  • v30.1 SMTP auth with SMTP_USE_TLS=false now uses PLAIN-NOENC explicitly instead of auto-discover

Beta — feedback welcome: [email protected]