-
-
Notifications
You must be signed in to change notification settings - Fork 426
Add custom header and URL query string options to the ntfy publisher #1695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| import json | ||
| import os | ||
| import re | ||
| import sys | ||
| import requests | ||
| from base64 import b64encode | ||
|
|
@@ -94,6 +95,11 @@ def send(html, text): | |
| user = get_setting_value('NTFY_USER') | ||
| pwd = get_setting_value('NTFY_PASSWORD') | ||
| verify_ssl = get_setting_value('NTFY_VERIFY_SSL') | ||
| custom_header_name = get_setting_value('NTFY_CUSTOMHEADER_NAME') | ||
| custom_header_value = get_setting_value('NTFY_CUSTOMHEADER_VALUE') | ||
| # Strip a leading '?' so both "p_token=..." and "?p_token=..." work; requests | ||
| # adds the '?' itself, and a leading one would produce a broken "??" in the URL. | ||
| url_query_string = get_setting_value('NTFY_URL_QUERY_STRING').lstrip('?') | ||
|
|
||
| # prepare request headers | ||
| headers = { | ||
|
|
@@ -112,13 +118,23 @@ def send(html, text): | |
| # add authorization header with hash | ||
| headers["Authorization"] = "Basic {}".format(basichash) | ||
|
|
||
| # Optional custom header, e.g. to authenticate through a reverse proxy / tunnel | ||
| # (Pangolin, Tailscale, ...) sitting in front of the ntfy instance. Skip it if it | ||
| # would clobber a built-in header (e.g. Authorization) so ntfy auth stays intact. | ||
| if custom_header_name != '' and custom_header_value != '': | ||
| if custom_header_name.lower() in {k.lower() for k in headers}: | ||
| mylog('none', [f'[{pluginName}] β Custom header "{custom_header_name}" collides with a built-in header; skipping it.']) | ||
| else: | ||
| headers[custom_header_name] = custom_header_value | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π Security & Privacy | π Major | β‘ Quick win π§© Analysis chainπ Script executed: #!/bin/bash
# Verify how the repository's installed requests version renders invalid header values.
python - <<'PY'
import inspect
import requests
from requests.exceptions import InvalidHeader, RequestException
print("InvalidHeader is RequestException:", issubclass(InvalidHeader, RequestException))
print(inspect.getsource(requests.utils._validate_header_part))
PYRepository: netalertx/NetAlertX Length of output: 1154 π Script executed: #!/bin/bash
set -euo pipefail
# Inspect the relevant function and nearby error handling in front/plugins/_publisher_ntfy/ntfy.py.
python3 - <<'PY'
from pathlib import Path
path = Path("front/plugins/_publisher_ntfy/ntfy.py")
lines = path.read_text().splitlines()
for start, end in [(1, 240)]:
for i in range(start, min(end, len(lines)) + 1):
print(f"{i:4d}: {lines[i-1]}")
PYRepository: netalertx/NetAlertX Length of output: 7586 Redact the custom header value from request errors. π€ Prompt for AI Agents |
||
|
|
||
| # call NTFY service | ||
| try: | ||
| response = requests.post("{}/{}".format( | ||
| get_setting_value('NTFY_HOST'), | ||
| get_setting_value('NTFY_TOPIC')), | ||
| data = text, | ||
| headers = headers, | ||
| params = url_query_string if url_query_string != '' else None, | ||
| verify = verify_ssl, | ||
| timeout = get_setting_value('NTFY_RUN_TIMEOUT') | ||
| ) | ||
|
|
@@ -132,9 +148,16 @@ def send(html, text): | |
| response_text = json.dumps(response.text) | ||
|
|
||
| except requests.exceptions.RequestException as e: | ||
| mylog('none', [f'[{pluginName}] β ERROR: ', e]) | ||
| # The exception message embeds the request URL, which may include a secret | ||
| # query string (e.g. a proxy token). Redact the query part before it is | ||
| # logged and persisted to the plugin result file / shown in the UI. | ||
| error_text = str(e) | ||
| if url_query_string != '': | ||
| error_text = re.sub(r'(\?)\S+', r'\1<redacted>', error_text) | ||
|
|
||
| mylog('none', [f'[{pluginName}] β ERROR: ', error_text]) | ||
|
|
||
| response_text = e | ||
| response_text = error_text | ||
|
|
||
| return response_text, response_status_code | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add sample values into the README.md in case people are confused how a valid value should look like