mirror of
https://github.com/multipleof4/ntfy.git
synced 2026-10-17 00:47:54 +00:00
Do not include secrets in the config hash
This commit is contained in:
+41
-36
@@ -4,14 +4,46 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
|||||||
|
|
||||||
## Current stable releases
|
## Current stable releases
|
||||||
|
|
||||||
| Component | Version | Release date |
|
| Component | Version | Release date |
|
||||||
|------------------|---------|--------------|
|
|------------------|---------|---------------|
|
||||||
| ntfy server | v2.26.3 | Jul 20, 2026 |
|
| ntfy server | v2.26.3 | Jul 20, 2026 |
|
||||||
| ntfy Android app | v1.24.0 | Mar 5, 2026 |
|
| ntfy Android app | v1.25.2 | July 23, 2026 |
|
||||||
| ntfy iOS app | v1.7.0 | May 30, 2026 |
|
| ntfy iOS app | v1.7.0 | May 30, 2026 |
|
||||||
|
|
||||||
Please check out the release notes for [upcoming releases](#not-released-yet) below.
|
Please check out the release notes for [upcoming releases](#not-released-yet) below.
|
||||||
|
|
||||||
|
## ntfy Android v1.25.2
|
||||||
|
Released July 23, 2026
|
||||||
|
|
||||||
|
This release makes the "connection lost" alert configurable and turns it off by default. Folks did not like it and many reached out
|
||||||
|
or even gave ntfy bad reviews. I heard you! You can re-enable the alert in the advanced settings.
|
||||||
|
|
||||||
|
The release also tries to be smarter about not retrying the connection at all if the app is in flight mode, or has no network. If there
|
||||||
|
is no network, ntfy now keeps the foreground service alive and shows a "Waiting for network" notification, then resumes automatically
|
||||||
|
once connectivity returns.
|
||||||
|
|
||||||
|
Another change related to the networking is that we now force-reconnect when the connection is changed, e.g. during transitions
|
||||||
|
from Wi-Fi to cellular network, or vice versa. That should allow for faster transitions during hand-overs.
|
||||||
|
|
||||||
|
We also increase the client-side WebSocket ping interval from 1 minute to 3 minutes, which should slightly improve battery life,
|
||||||
|
especially when paired with increaseing the server-side `keepalive-interval` in your self-hosted server.
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
|
||||||
|
* Add configurable "Alert when connection is lost" setting, turned off by default ([#1665](https://github.com/binwiederhier/ntfy/issues/1665), [#1662](https://github.com/binwiederhier/ntfy/issues/1662), [#1652](https://github.com/binwiederhier/ntfy/issues/1652), [#1655](https://github.com/binwiederhier/ntfy/issues/1655), thanks to [@tintamarre](https://github.com/tintamarre), [@sjozs](https://github.com/sjozs), [@TheRealOne78](https://github.com/TheRealOne78), and [@DAE51D](https://github.com/DAE51D) for reporting)
|
||||||
|
* Handle "no network" gracefully: when the device is offline or in airplane mode, ntfy now stops retrying, suppresses the connection-lost alert, and keeps the foreground service alive with a "Waiting for network" notification, resuming instant delivery automatically when connectivity returns ([ntfy-android#165](https://github.com/binwiederhier/ntfy-android/pull/165), thanks to [@tintamarre](https://github.com/tintamarre) for the contribution, and [#1709](https://github.com/binwiederhier/ntfy/issues/1709), thanks to [@isaitgirl](https://github.com/isaitgirl) for reporting)
|
||||||
|
* Improve battery life by increasing WebSocket client ping interval from 1 min to 3 min, and reconnect instantly on Wi-Fi/cellular/VPN transitions ([ntfy-android#113](https://github.com/binwiederhier/ntfy-android/pull/113), thanks to [@ftilde](https://github.com/ftilde) for the investigation)
|
||||||
|
* Disable UnifiedPush components when UnifiedPush is disabled in settings ([ntfy-android#168](https://github.com/binwiederhier/ntfy-android/pull/168), thanks to [@p1gp1g](https://github.com/p1gp1g) for the contribution)
|
||||||
|
|
||||||
|
**Bug fixes + maintenance:**
|
||||||
|
|
||||||
|
* Fix the "connection lost" alert briefly disappearing and re-firing when roaming between networks (e.g. Wi-Fi to cellular), by no longer cancelling it during the transient no-network gap of a handover
|
||||||
|
* Fix the "connection lost" alert repeatedly waking the screen while a server stayed unreachable, by no longer re-posting the alert once it is already showing
|
||||||
|
* Fix the "connection lost" alert firing late, erratically, or not at all when a connection kept dropping (e.g. a flaky server) rather than being refused outright, by tracking how long the connection has been down independently of whether the drop warrants a UI error
|
||||||
|
* Undo automatic phone number linking for numbers in message body ([ntfy-android#170](https://github.com/binwiederhier/ntfy-android/pull/170), thanks to [@acortelyou](https://github.com/acortelyou) for the contribution)
|
||||||
|
* Fix subscription icons disappearing after a few days due to Android clearing cache ([#1322](https://github.com/binwiederhier/ntfy/issues/1322), thanks to [@mcanning](https://github.com/mcanning) for reporting)
|
||||||
|
* Fix UnifiedPush `failed_reason` being sent as an enum instead of a string, which caused an exception in receiving apps that read it as a string extra ([ntfy-android#182](https://github.com/binwiederhier/ntfy-android/pull/182), thanks to [@p1gp1g](https://github.com/p1gp1g) for the contribution)
|
||||||
|
|
||||||
### ntfy server v2.26.3
|
### ntfy server v2.26.3
|
||||||
Released July 20, 2026
|
Released July 20, 2026
|
||||||
|
|
||||||
@@ -2021,6 +2053,10 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
|||||||
|
|
||||||
### ntfy server v2.27.0 (UNRELEASED)
|
### ntfy server v2.27.0 (UNRELEASED)
|
||||||
|
|
||||||
|
**Security:**
|
||||||
|
|
||||||
|
* Exclude secrets (Stripe/Twilio/web push keys, SMTP password, provisioned users and tokens) from the config hash served to the web app
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|
||||||
* Allow logging in with your verified primary email address (in addition to your username), so a password reset no longer leaves you unable to sign in when you only remember the email you signed up with
|
* Allow logging in with your verified primary email address (in addition to your username), so a password reset no longer leaves you unable to sign in when you only remember the email you signed up with
|
||||||
@@ -2030,37 +2066,6 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
|
|||||||
* Fix Twilio phone calls and phone number verifications failing silently when Twilio rejected the request, and move the Twilio integration into its own `twilio` package
|
* Fix Twilio phone calls and phone number verifications failing silently when Twilio rejected the request, and move the Twilio integration into its own `twilio` package
|
||||||
* Move the Prometheus metrics into a dedicated `metrics` package
|
* Move the Prometheus metrics into a dedicated `metrics` package
|
||||||
|
|
||||||
### ntfy Android v1.25.2 (UNRELEASED)
|
|
||||||
|
|
||||||
This release makes the "connection lost" alert configurable and turns it off by default. Folks did not like it and many reached out
|
|
||||||
or even gave ntfy bad reviews. I heard you! You can re-enable the alert in the advanced settings.
|
|
||||||
|
|
||||||
The release also tries to be smarter about not retrying the connection at all if the app is in flight mode, or has no network. If there
|
|
||||||
is no network, ntfy now keeps the foreground service alive and shows a "Waiting for network" notification, then resumes automatically
|
|
||||||
once connectivity returns.
|
|
||||||
|
|
||||||
Another change related to the networking is that we now force-reconnect when the connection is changed, e.g. during transitions
|
|
||||||
from Wi-Fi to cellular network, or vice versa. That should allow for faster transitions during hand-overs.
|
|
||||||
|
|
||||||
We also increase the client-side WebSocket ping interval from 1 minute to 3 minutes, which should slightly improve battery life,
|
|
||||||
especially when paired with increaseing the server-side `keepalive-interval` in your self-hosted server.
|
|
||||||
|
|
||||||
**Features:**
|
|
||||||
|
|
||||||
* Add configurable "Alert when connection is lost" setting, turned off by default ([#1665](https://github.com/binwiederhier/ntfy/issues/1665), [#1662](https://github.com/binwiederhier/ntfy/issues/1662), [#1652](https://github.com/binwiederhier/ntfy/issues/1652), [#1655](https://github.com/binwiederhier/ntfy/issues/1655), thanks to [@tintamarre](https://github.com/tintamarre), [@sjozs](https://github.com/sjozs), [@TheRealOne78](https://github.com/TheRealOne78), and [@DAE51D](https://github.com/DAE51D) for reporting)
|
|
||||||
* Handle "no network" gracefully: when the device is offline or in airplane mode, ntfy now stops retrying, suppresses the connection-lost alert, and keeps the foreground service alive with a "Waiting for network" notification, resuming instant delivery automatically when connectivity returns ([ntfy-android#165](https://github.com/binwiederhier/ntfy-android/pull/165), thanks to [@tintamarre](https://github.com/tintamarre) for the contribution, and [#1709](https://github.com/binwiederhier/ntfy/issues/1709), thanks to [@isaitgirl](https://github.com/isaitgirl) for reporting)
|
|
||||||
* Improve battery life by increasing WebSocket client ping interval from 1 min to 3 min, and reconnect instantly on Wi-Fi/cellular/VPN transitions ([ntfy-android#113](https://github.com/binwiederhier/ntfy-android/pull/113), thanks to [@ftilde](https://github.com/ftilde) for the investigation)
|
|
||||||
* Disable UnifiedPush components when UnifiedPush is disabled in settings ([ntfy-android#168](https://github.com/binwiederhier/ntfy-android/pull/168), thanks to [@p1gp1g](https://github.com/p1gp1g) for the contribution)
|
|
||||||
|
|
||||||
**Bug fixes + maintenance:**
|
|
||||||
|
|
||||||
* Fix the "connection lost" alert briefly disappearing and re-firing when roaming between networks (e.g. Wi-Fi to cellular), by no longer cancelling it during the transient no-network gap of a handover
|
|
||||||
* Fix the "connection lost" alert repeatedly waking the screen while a server stayed unreachable, by no longer re-posting the alert once it is already showing
|
|
||||||
* Fix the "connection lost" alert firing late, erratically, or not at all when a connection kept dropping (e.g. a flaky server) rather than being refused outright, by tracking how long the connection has been down independently of whether the drop warrants a UI error
|
|
||||||
* Undo automatic phone number linking for numbers in message body ([ntfy-android#170](https://github.com/binwiederhier/ntfy-android/pull/170), thanks to [@acortelyou](https://github.com/acortelyou) for the contribution)
|
|
||||||
* Fix subscription icons disappearing after a few days due to Android clearing cache ([#1322](https://github.com/binwiederhier/ntfy/issues/1322), thanks to [@mcanning](https://github.com/mcanning) for reporting)
|
|
||||||
* Fix UnifiedPush `failed_reason` being sent as an enum instead of a string, which caused an exception in receiving apps that read it as a string extra ([ntfy-android#182](https://github.com/binwiederhier/ntfy-android/pull/182), thanks to [@p1gp1g](https://github.com/p1gp1g) for the contribution)
|
|
||||||
|
|
||||||
### ntfy iOS app v1.8.0 (UNRELEASED)
|
### ntfy iOS app v1.8.0 (UNRELEASED)
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
|||||||
+12
-8
@@ -130,9 +130,9 @@ type Config struct {
|
|||||||
AuthFile string
|
AuthFile string
|
||||||
AuthStartupQueries string
|
AuthStartupQueries string
|
||||||
AuthDefault user.Permission
|
AuthDefault user.Permission
|
||||||
AuthUsers []*user.User
|
AuthUsers []*user.User `hash:"-"`
|
||||||
AuthAccess map[string][]*user.Grant
|
AuthAccess map[string][]*user.Grant
|
||||||
AuthTokens map[string][]*user.Token
|
AuthTokens map[string][]*user.Token `hash:"-"`
|
||||||
AuthBcryptCost int
|
AuthBcryptCost int
|
||||||
AuthStatsQueueWriterInterval time.Duration
|
AuthStatsQueueWriterInterval time.Duration
|
||||||
AuthAccessCacheEnabled bool // Enables the in-memory ACL cache (high volume servers only)
|
AuthAccessCacheEnabled bool // Enables the in-memory ACL cache (high volume servers only)
|
||||||
@@ -153,17 +153,17 @@ type Config struct {
|
|||||||
FirebasePollInterval time.Duration
|
FirebasePollInterval time.Duration
|
||||||
FirebaseQuotaExceededPenaltyDuration time.Duration
|
FirebaseQuotaExceededPenaltyDuration time.Duration
|
||||||
UpstreamBaseURL string
|
UpstreamBaseURL string
|
||||||
UpstreamAccessToken string
|
UpstreamAccessToken string `hash:"-"`
|
||||||
SMTPSenderAddr string
|
SMTPSenderAddr string
|
||||||
SMTPSenderUser string
|
SMTPSenderUser string
|
||||||
SMTPSenderPass string
|
SMTPSenderPass string `hash:"-"`
|
||||||
SMTPSenderFrom string
|
SMTPSenderFrom string
|
||||||
SMTPSenderVerify bool
|
SMTPSenderVerify bool
|
||||||
SMTPServerListen string
|
SMTPServerListen string
|
||||||
SMTPServerDomain string
|
SMTPServerDomain string
|
||||||
SMTPServerAddrPrefix string
|
SMTPServerAddrPrefix string
|
||||||
TwilioAccount string
|
TwilioAccount string
|
||||||
TwilioAuthToken string
|
TwilioAuthToken string `hash:"-"`
|
||||||
TwilioPhoneNumber string
|
TwilioPhoneNumber string
|
||||||
TwilioCallsBaseURL string
|
TwilioCallsBaseURL string
|
||||||
TwilioVerifyBaseURL string
|
TwilioVerifyBaseURL string
|
||||||
@@ -198,8 +198,8 @@ type Config struct {
|
|||||||
BehindProxy bool // If true, the server will trust the proxy client IP header to determine the client IP address (IPv4 and IPv6 supported)
|
BehindProxy bool // If true, the server will trust the proxy client IP header to determine the client IP address (IPv4 and IPv6 supported)
|
||||||
ProxyForwardedHeader string // The header field to read the real/client IP address from, if BehindProxy is true, defaults to "X-Forwarded-For" (IPv4 and IPv6 supported)
|
ProxyForwardedHeader string // The header field to read the real/client IP address from, if BehindProxy is true, defaults to "X-Forwarded-For" (IPv4 and IPv6 supported)
|
||||||
ProxyTrustedPrefixes []netip.Prefix // List of trusted proxy networks (IPv4 or IPv6) that will be stripped from the Forwarded header if BehindProxy is true
|
ProxyTrustedPrefixes []netip.Prefix // List of trusted proxy networks (IPv4 or IPv6) that will be stripped from the Forwarded header if BehindProxy is true
|
||||||
StripeSecretKey string
|
StripeSecretKey string `hash:"-"`
|
||||||
StripeWebhookKey string
|
StripeWebhookKey string `hash:"-"`
|
||||||
StripePriceCacheDuration time.Duration
|
StripePriceCacheDuration time.Duration
|
||||||
BillingContact string
|
BillingContact string
|
||||||
EnableSignup bool // Enable creation of accounts via API and UI
|
EnableSignup bool // Enable creation of accounts via API and UI
|
||||||
@@ -208,7 +208,7 @@ type Config struct {
|
|||||||
EnableReservations bool // Allow users with role "user" to own/reserve topics
|
EnableReservations bool // Allow users with role "user" to own/reserve topics
|
||||||
EnableMetrics bool
|
EnableMetrics bool
|
||||||
AccessControlAllowOrigin string // CORS header field to restrict access from web clients
|
AccessControlAllowOrigin string // CORS header field to restrict access from web clients
|
||||||
WebPushPrivateKey string
|
WebPushPrivateKey string `hash:"-"`
|
||||||
WebPushPublicKey string
|
WebPushPublicKey string
|
||||||
WebPushFile string
|
WebPushFile string
|
||||||
WebPushEmailAddress string
|
WebPushEmailAddress string
|
||||||
@@ -342,6 +342,10 @@ func (c *Config) Hash() string {
|
|||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
field := v.Field(i)
|
field := v.Field(i)
|
||||||
fieldName := t.Field(i).Name
|
fieldName := t.Field(i).Name
|
||||||
|
// Secrets must not feed the hash
|
||||||
|
if t.Field(i).Tag.Get("hash") == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Try to marshal the field and skip if it fails (e.g. *template.Template, netip.Prefix)
|
// Try to marshal the field and skip if it fails (e.g. *template.Template, netip.Prefix)
|
||||||
if b, err := json.Marshal(field.Interface()); err == nil {
|
if b, err := json.Marshal(field.Interface()); err == nil {
|
||||||
result += fmt.Sprintf("%s:%s|", fieldName, string(b))
|
result += fmt.Sprintf("%s:%s|", fieldName, string(b))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package server_test
|
|||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"heckel.io/ntfy/v2/server"
|
"heckel.io/ntfy/v2/server"
|
||||||
|
"heckel.io/ntfy/v2/user"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,3 +12,24 @@ func TestConfig_New(t *testing.T) {
|
|||||||
assert.Equal(t, ":80", c.ListenHTTP)
|
assert.Equal(t, ":80", c.ListenHTTP)
|
||||||
assert.Equal(t, server.DefaultKeepaliveInterval, c.KeepaliveInterval)
|
assert.Equal(t, server.DefaultKeepaliveInterval, c.KeepaliveInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfig_HashExcludesSecrets(t *testing.T) {
|
||||||
|
// The config hash is served to browsers (ConfigHash, for webapp change detection), so
|
||||||
|
// secret material must not feed it: a weak secret would otherwise be offline-brute-forceable
|
||||||
|
// against a publicly visible hash.
|
||||||
|
conf1 := server.NewConfig()
|
||||||
|
conf2 := server.NewConfig()
|
||||||
|
conf2.StripeSecretKey = "sk_live_topsecret"
|
||||||
|
conf2.StripeWebhookKey = "whsec_topsecret"
|
||||||
|
conf2.TwilioAuthToken = "twilio-auth-token"
|
||||||
|
conf2.UpstreamAccessToken = "tk_upstream"
|
||||||
|
conf2.WebPushPrivateKey = "web-push-private-key"
|
||||||
|
conf2.SMTPSenderPass = "hunter2"
|
||||||
|
conf2.AuthUsers = []*user.User{{Name: "phil", Hash: "$2a$10$somebcrypthash"}}
|
||||||
|
conf2.AuthTokens = map[string][]*user.Token{"phil": {{Value: "tk_secrettoken"}}}
|
||||||
|
assert.Equal(t, conf1.Hash(), conf2.Hash())
|
||||||
|
// Non-secret fields must still change the hash
|
||||||
|
conf3 := server.NewConfig()
|
||||||
|
conf3.BaseURL = "https://ntfy.example.com"
|
||||||
|
assert.NotEqual(t, conf1.Hash(), conf3.Hash())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user