From b409c89d3b2108cb9b3e12d5c40b9a650ba0054b Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Wed, 23 Mar 2022 14:29:55 -0400 Subject: [PATCH] Do not allow comma in topic name in publish via GET endpoint (no ticket) --- docs/releases.md | 10 ++++++++-- server/server.go | 20 ++++++++++---------- server/server_test.go | 8 ++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index c0946d27..d09dcd0f 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -11,17 +11,23 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release * Download attachments to cache folder ([#181](https://github.com/binwiederhier/ntfy/issues/181)) * Regularly delete attachments for deleted notifications ([#142](https://github.com/binwiederhier/ntfy/issues/142)) -Bugs: +**Bugs:** * IllegalStateException: Failed to build unique file ([#177](https://github.com/binwiederhier/ntfy/issues/177), thanks to [@Fallenbagel](https://github.com/Fallenbagel) for reporting) * SQLiteConstraintException: Crash during UP registration ([#185](https://github.com/binwiederhier/ntfy/issues/185)) * Refresh preferences screen after settings import (#183, thanks to [@cmeis](https://github.com/cmeis) for reporting) -Thanks: +**Thanks:** * Many thanks to [@cmeis](https://github.com/cmeis), [@Fallenbagel](https://github.com/Fallenbagel), [@Joeharrison94](https://github.com/Joeharrison94), and [@rogeliodh](https://github.com/rogeliodh) for input on the new attachment logic, and for testing the release +## ntfy server v1.19.0 (UNRELEASED) + +**Bugs:** + +* Do not allow comma in topic name in publish via GET endpoint (no ticket) + --> ## ntfy server v1.18.1 diff --git a/server/server.go b/server/server.go index a0de013d..0e81cb63 100644 --- a/server/server.go +++ b/server/server.go @@ -55,15 +55,15 @@ type handleFunc func(http.ResponseWriter, *http.Request, *visitor) error var ( // If changed, don't forget to update Android App and auth_sqlite.go - topicRegex = regexp.MustCompile(`^[-_A-Za-z0-9]{1,64}$`) // No /! - topicPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app! - extTopicPathRegex = regexp.MustCompile(`^/[^/]+\.[^/]+/[-_A-Za-z0-9]{1,64}$`) // Extended topic path, for web-app, e.g. /example.com/mytopic - jsonPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/json$`) - ssePathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/sse$`) - rawPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/raw$`) - wsPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/ws$`) - authPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/auth$`) - publishPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/(publish|send|trigger)$`) + topicRegex = regexp.MustCompile(`^[-_A-Za-z0-9]{1,64}$`) // No /! + topicPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app! + externalTopicPathRegex = regexp.MustCompile(`^/[^/]+\.[^/]+/[-_A-Za-z0-9]{1,64}$`) // Extended topic path, for web-app, e.g. /example.com/mytopic + jsonPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/json$`) + ssePathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/sse$`) + rawPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/raw$`) + wsPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/ws$`) + authPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/auth$`) + publishPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/(publish|send|trigger)$`) webConfigPath = "/config.js" staticRegex = regexp.MustCompile(`^/static/.+`) @@ -293,7 +293,7 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.limitRequests(s.authRead(s.handleSubscribeWS))(w, r, v) } else if r.Method == http.MethodGet && authPathRegex.MatchString(r.URL.Path) { return s.limitRequests(s.authRead(s.handleTopicAuth))(w, r, v) - } else if r.Method == http.MethodGet && (topicPathRegex.MatchString(r.URL.Path) || extTopicPathRegex.MatchString(r.URL.Path)) { + } else if r.Method == http.MethodGet && (topicPathRegex.MatchString(r.URL.Path) || externalTopicPathRegex.MatchString(r.URL.Path)) { return s.handleTopic(w, r) } return errHTTPNotFound diff --git a/server/server_test.go b/server/server_test.go index e5106d9c..0827cc90 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -203,6 +203,14 @@ func TestServer_PublishPriority(t *testing.T) { require.Equal(t, 40007, toHTTPError(t, response.Body.String()).Code) } +func TestServer_PublishGETOnlyOneTopic(t *testing.T) { + // This tests a bug that allowed publishing topics with a comma in the name (no ticket) + + s := newTestServer(t, newTestConfig(t)) + response := request(t, s, "GET", "/mytopic,mytopic2/publish?m=hi", "", nil) + require.Equal(t, 404, response.Code) +} + func TestServer_PublishNoCache(t *testing.T) { s := newTestServer(t, newTestConfig(t))