Apprise URLs: ntfy://topic, the form's own example, is refused on a default instance because the topic is checked as a hostname #16
Labels
No labels
bug
documentation
enhancement
security
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo-apprise#16
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo-apprise at
7637d899d, running the help text's own examples throughvalidate()with Apprise 1.13.1 and a stub resolver.Related to #1.
names_a_server()answers per class: does the URL template declare ahosttoken. Several services declare one and keep something other than the dialled address there. The value is turned intohttps://<value>and handed tocheck_destination, which refuses a name that does not resolve, so a connection to an entirely public service is refused with a sentence about private addresses. The docstring says this costs one scheme,wechat; it costs at least six, and one of them is the example printed under the field.src/postulo_apprise/notifier.py:96-99(names_a_server:return "host" in template);:110-120(destination_of);:184-187(the refusal sentence, which printsserver.host);:144-145(the help text: "tgram://bot-token/chat-id, ntfy://topic, …");:91-94(the docstring: "What that costs, in this Apprise, iswechat"). In Apprise 1.13.1:plugins/ntfy.py:980-998chooses cloud mode when the host slot is not followed by a topic and keeps the topic inhost, and:533-535then sends tocloud_notify_url(https://ntfy.sh,:164);plugins/mailgun.py:140-141,plugins/sparkpost.py:163-164,plugins/smtp2go.py:112-113andplugins/sendpulse.py:114-115declarehostas the sender's "Domain" and send to their own API.ntfy://my-topic. Checked on the snapshot: Apprise reportsmode='cloud',host='my-topic';destination_ofreturnshttps://my-topic; the form answers "ntfy at my-topic: That hostname could not be resolved. Connections may only reach private or local addresses when the operator sets POSTULO_CONNECTIONS_ALLOW_PRIVATE=true." A Mailgun line is refused the same way when its sending domain has no address record, which is usual for a subdomain that carries only MX and TXT records; so are SparkPost, SMTP2GO and SendPulse lines.ntfy://ntfy.sh/my-topicis accepted, but nothing on the form suggests it. A topic that happens to match a name the resolver knows (a Compose service, say) is refused or accepted for reasons that have nothing to do with ntfy.server.hostas if it were an address; for cloud ntfy that is the topic, which is all that protects a topic on ntfy.sh, and when the same refusal is raised at send time (_client,:190-195) it is stored on the connection and written to the log by the core (notifications/service.py:86-89). No test covers a cloud-mode line: the tests usentfy://ntfy.example.org/postuloandntfy://internal/postuloonly.mode: in cloud mode the destination isntfy.sh(or none), nothost.hostas not dialled.smtp=andkeyfile=arguments need (filed alongside this issue), so one table of reviewed schemes with "what does this server dial" answers both.server.host, unless the value is known to be an address.Done when
tests/test_apprise.py, withPOSTULO_CONNECTIONS_ALLOW_PRIVATEoff and a resolver that knows no single-label name, showsvalidate()accepting every example in the field's help text,ntfy://topicincluded, and a Mailgun line whose domain does not resolve.ntfy://internal/postulo(a server of the person's own) is still checked and refused.Fixed by pull request #23.