-
2.7.0
StableAll checks were successfulCI / Lint + Static Analysis (push) Successful in 1m56sCI / Unit Tests (PHP 8.3) (push) Successful in 1m49sCI / Unit Tests (PHP 8.4) (push) Successful in 1m48sCI / Unit Tests (PHP 8.5) (push) Successful in 1m52sRelease / Verify tag, version and changelog (push) Successful in 3sRelease / Lint + Static Analysis (push) Successful in 1m53sRelease / Unit Tests (PHP 8.5) (push) Successful in 1m38sRelease / Build zip and publish release (push) Successful in 3sRelease / Unit Tests (PHP 8.3) (push) Successful in 1m37sRelease / Unit Tests (PHP 8.4) (push) Successful in 1m37sreleased this
2026-10-16 22:36:07 -07:00 | 1 commits to main since this releaseSecurity
- DNS pinning now works with the cURL transport. The pinned IP was passed as
$args['curl'], which WordPress never reads, so cURL looked the hostname up again when connecting, and a DNS rebind could get past the private-IP check.CURLOPT_RESOLVEis now set on the cURL handle from thehttp_api_curlaction, for this request only (#3). - Loopback is now checked on the resolved IP as well as on the literal URL host. Before,
[::],0177.0.0.1,2130706433,127.1or a name resolving to 127.x fell through to the private-range check, so the Allow Private IPs setting opened localhost. Only theapprise_notifications_allow_localhostfilter can open loopback now.0.0.0.0/8and::also count as loopback (#4). - The private-IP check now blocks non-global ranges that PHP's
FILTER_FLAG_NO_PRIV_RANGE/FILTER_FLAG_NO_RES_RANGElet through:100.64.0.0/10(CGNAT, Tailscale, and Alibaba Cloud metadata at100.100.100.200),192.0.0.0/24,198.18.0.0/15, the documentation ranges,224.0.0.0/4, and in IPv664:ff9b:1::/48,100::/64, Teredo2001::/32,2001:db8::/32,fec0::/10andff00::/8. NAT64 (64:ff9b::/96) and 6to4 (2002::/16) addresses are checked by the IPv4 address they embed, so64:ff9b::a9fe:a9feis treated as169.254.169.254. Allow Private IPs and theapprise_notifications_allow_private_ipfilter still open these ranges (#5). - On multisite, only a super admin can change Allow Private IPs. A subsite administrator has
manage_optionsbut not network-level trust, and could use the setting with Test Connection to probe hosts and ports on the server's internal network. For other users the checkbox is now disabled, and anything they submit for it is ignored. Values already saved are not changed: if a subsite admin turned the setting on before this release, it stays on until a super admin turns it off (#6). - Allow Private IPs no longer opens link-local and cloud metadata addresses:
169.254.0.0/16(metadata at169.254.169.254on AWS, GCP, Azure and others),fe80::/10, AWS IMDS over IPv6 atfd00:ec2::254, and Alibaba Cloud metadata at100.100.100.200. No Apprise server runs there. Theapprise_notifications_allow_private_ipfilter can still open them, but it getsfalseas the default for these addresses whatever the setting, and only a stricttruelets one through (#7).
Fixed
- Email suppression → Matching events only with
user_registeron no longer blocks the new user's own set-password email. Only the admin's new-user email is suppressed, which is the one the Apprise notification replaces. Before, a newly registered user never got their login link (#8). - Email suppression now needs an Apprise API URL as well as the plugin being enabled. With no URL set, All emails used to drop every site email, password resets included, and Matching events only dropped the emails it covers, with no Apprise notification sent in their place. The settings page now warns when a suppression mode is chosen but no API URL is set. A URL that is set but unreachable still can't be detected before WordPress sends mail (#9).
- The Apprise notice about a new plugin version now respects the plugin's Enable Notifications switch. Before, a site with notifications turned off but Check for new versions on kept sending update notices to the Apprise URL. With notifications off, the daily notice job is unscheduled; new versions still show on the Plugins and Updates screens with one-click update. On multisite the main site's switch applies, since only the main site sends the notice (#10).
Changed
- The Theme Auto-Updated event is now labelled Theme Updated. It has always fired for manual theme updates as well as automatic ones. The event key (
theme_update) is unchanged. - The Enable Notifications description no longer says it doesn't affect the update checker, which stopped being true with the fix above.
- README and readme.txt reviewed against the code: the README's event list now has all 17 events and their defaults, its custom-event example uses the dispatcher instead of the
apprise_notifications_event_typesfilter removed in 2.4.1, it lists every public hook, and it no longer describes delivery as synchronous. readme.txt drops a Screenshots section with no screenshots (#12).
Removed
- Raw cURL options returned in
$args['curl']byapprise_notifications_request_argsare no longer filtered. WordPress never applied them, so the filtering did nothing.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- DNS pinning now works with the cURL transport. The pinned IP was passed as
-
2.6.0
StableAll checks were successfulCI / Unit Tests (PHP 8.3) (push) Successful in 1m41sCI / Unit Tests (PHP 8.4) (push) Successful in 1m44sCI / Unit Tests (PHP 8.5) (push) Successful in 1m47sRelease / Verify tag, version and changelog (push) Successful in 3sRelease / Lint + Static Analysis (push) Successful in 1m49sCI / Lint + Static Analysis (push) Successful in 1m59sRelease / Unit Tests (PHP 8.4) (push) Successful in 1m41sRelease / Unit Tests (PHP 8.3) (push) Successful in 2m2sRelease / Unit Tests (PHP 8.5) (push) Successful in 1m36sRelease / Build zip and publish release (push) Successful in 3sreleased this
2026-10-16 16:58:55 -07:00 | 13 commits to main since this releaseAdded
- Available updates now appear on Plugins and Dashboard → Updates with one-click update from the release zip. The plugin header declares
Update URI: https://git.pickysysadmin.ca/eric/apprise-wordpress-notifications/releases, and the opt-in update check answers core'supdate_plugins_git.pickysysadmin.cafilter with the highest release in the repo'sreleases.rss. Results are cached for 12 hours (1 hour after a failed fetch) and dropped when the setting is toggled. TheUpdate URIalso stops wordpress.org from offering a same-slug plugin as an update.
Changed
- Minimum PHP version raised from 8.0 to 8.3 (
Requires PHP: 8.3). PHP 8.0 and 8.1 are end of life, and 8.2 reaches end of life in December 2026. Sites still on an older PHP should stay on 2.5.4 until they upgrade PHP. - The update check replaces its custom admin notice, dismiss button and AJAX handler with core's update UI. The Apprise notification (once per new version, from a daily WP-Cron job) is unchanged, except that it now links to Dashboard → Updates.
- On multisite, the main site's Check for new versions setting applies to the whole network, and only the main site sends the Apprise notification. Previously each site checked and notified separately.
- Release zips are now built by CI from tagged commits and attached to each release as
apprise-wordpress-notifications.X.Y.Z.zip, withapprise-wordpress-notifications/as the root folder. Install from that zip, not theSource Codearchive.
Security
- The update check sends an
Apprise-Notifications/<version>user agent instead of core's default, which includes the site's URL. A cached version that isn't a release-style version number is discarded and refetched rather than used in the download URL.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Available updates now appear on Plugins and Dashboard → Updates with one-click update from the release zip. The plugin header declares
-
2.5.4 Stable
released this
2026-06-28 09:52:08 -07:00 | 19 commits to main since this releaseForgejo migration and update checker hardening
Fixed update checker compatibility with Forgejo. Forgejo's /releases.rss feed uses the same URL path as Gitea, but item titles are plain version numbers (e.g. 2.5.3) rather than v-prefixed. The checker now extracts the version from basename(link) instead of the item title, and filters feed items by /releases/tag/ in the link URL — making it robust against any future title format changes regardless of forge software.
Updated internal docstrings from "Gitea" to "Forgejo".
Full changelog: 2.5.3...2.5.4
Downloads
-
Source code (ZIP)
10 downloads
-
Source code (TAR.GZ)
11 downloads
-
Source code (ZIP)
-
2.5.3 Stable
released this
2026-06-28 09:42:33 -07:00 | 21 commits to main since this releaseSecurity
- Block
CURLOPT_URLinsanitize_curl_options()—CURLOPT_URL(integer10002) was absent from the cURL option blocklist. A rogue plugin hookingapprise_notifications_request_argscould inject this option to redirect any Apprise API request to an arbitrary URL after SSRF validation had already passed. TheCURLOPT_RESOLVEDNS pin applied to the original Apprise hostname has no effect on a substituted target, so loopback services, RFC 1918 hosts, and cloud metadata endpoints (e.g.169.254.169.254) were reachable. Exploitation requires server-side code execution via a malicious or compromised plugin.
Full changelog:
2.5.2...2.5.3Downloads
-
Source code (ZIP)
9 downloads
-
Source code (TAR.GZ)
8 downloads
- Block
-
2.5.2 Stable
released this
2026-06-27 22:48:18 -07:00 | 22 commits to main since this releaseSecurity fixes and hardening
-
Fixed IPv4-mapped IPv6 SSRF bypass (HIGH) — Addresses in the
::ffff:0:0/96 range (e.g. ::ffff:169.254.169.254, ::ffff:7f00:1)
bypassed both the loopback check and private/reserved range check because
PHP's FILTER_FLAG_NO_PRIV_RANGE / FILTER_FLAG_NO_RES_RANGE do not
cover that range. Both resolve_and_validate_url() and
is_loopback_address() now unwrap IPv4-mapped addresses before range
checks, mirroring WordPress core's wp_http_validate_url(). -
Added CURLOPT_CAINFO/CAPATH to sanitize_curl_options() blocklist (LOW)
— Both options substitute the CA bundle used for SSL verification and were
absent despite all other SSL-bypass cURL options being blocked. -
Fixed email suppression 'matching' mode not suppressing pingback emails
when pingback_new is enabled but comment_new is disabled — the
notify_post_author / notify_moderator filters were only registered
when comment_new was on. -
Updated email suppression 'all' mode description to explicitly warn that
password reset emails have no Apprise notification substitute. -
Updated Stateless URLs field description to clarify that Apprise makes
outbound HTTP requests to those URLs, including HTTP-dispatching schemes
(json://, xml://, form://).
Downloads
-
Source code (ZIP)
8 downloads
-
Source code (TAR.GZ)
8 downloads
-