v32.3
gorhill/uBlockv32.3Jun 15, 2026by pierre-b
AI Summary
This release addresses critical security vulnerabilities in broadcast data-feed endpoints and workspace permissions, alongside fixes for task scheduling and email template handling.
Key Highlights
- Broadcast data-feed endpoints fixed SSRF vulnerability and now require broadcasts:write permission.
- All broadcast operations now enforce strict workspace permissions to prevent unauthorized mutations.
- Task scheduler now executes tasks in-process to fix connection refused errors in single-instance deployments.
- Fix for excluding unconfirmed contacts from double opt-in broadcast lists.
- Template variables like {{ workspace.base_url }} now render correctly in the preview tab.
New Features
- Granular permission endpoints for custom field labels and blog settings.
- Workspace template variables now render in the preview tab.
Full Release Notes
- **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.