From 5c882ae8930999a2d78a94293fbdbef191ce9754 Mon Sep 17 00:00:00 2001 From: sricursion Date: Sun, 12 Jul 2026 20:08:01 +0530 Subject: [PATCH] fix: parse PUSHER_USE_SSL env var as boolean string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PUSHER_USE_SSL was compared with `is False`, so any string value — including "false" set via docker-compose or k8s env — enabled SSL. Parse it with the same starlette `config(..., cast=bool)` idiom used across the codebase. Unrecognized values keep SSL enabled (fail-secure, matching pre-fix behavior) and log a warning. Fixes #6582 --- keep/api/core/dependencies.py | 14 ++++++++- tests/test_pusher_client.py | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/test_pusher_client.py diff --git a/keep/api/core/dependencies.py b/keep/api/core/dependencies.py index 0dfd0d934e..51a9e325ba 100644 --- a/keep/api/core/dependencies.py +++ b/keep/api/core/dependencies.py @@ -65,6 +65,18 @@ def get_pusher_client() -> Pusher | None: logger.debug("Pusher is disabled or missing environment variables") return None + try: + pusher_use_ssl = config("PUSHER_USE_SSL", default=False, cast=bool) + except ValueError: + # Unrecognized values previously enabled SSL, so keep SSL on + # (fail-secure) rather than silently downgrading to plaintext. + logger.warning( + "Invalid PUSHER_USE_SSL value, keeping SSL enabled. " + "Use 'true' or 'false'.", + extra={"pusher_use_ssl": os.environ.get("PUSHER_USE_SSL")}, + ) + pusher_use_ssl = True + # TODO: defaults on open source no docker try: pusher = Pusher( @@ -77,7 +89,7 @@ def get_pusher_client() -> Pusher | None: app_id=pusher_app_id, key=pusher_app_key, secret=pusher_app_secret, - ssl=False if os.environ.get("PUSHER_USE_SSL", False) is False else True, + ssl=pusher_use_ssl, cluster=os.environ.get("PUSHER_CLUSTER"), ) except ValueError: diff --git a/tests/test_pusher_client.py b/tests/test_pusher_client.py new file mode 100644 index 0000000000..85e4af8acb --- /dev/null +++ b/tests/test_pusher_client.py @@ -0,0 +1,55 @@ +import pytest + +from keep.api.core import dependencies + + +class FakePusher: + def __init__(self, **kwargs): + self.kwargs = kwargs + + +@pytest.fixture +def pusher_env(monkeypatch): + monkeypatch.setattr(dependencies, "Pusher", FakePusher) + monkeypatch.setenv("PUSHER_APP_ID", "1") + monkeypatch.setenv("PUSHER_APP_KEY", "test-key") + monkeypatch.setenv("PUSHER_APP_SECRET", "test-secret") + monkeypatch.delenv("PUSHER_DISABLED", raising=False) + monkeypatch.delenv("PUSHER_USE_SSL", raising=False) + + +@pytest.mark.parametrize( + "value,expected", + [ + ("false", False), + ("False", False), + ("0", False), + ("true", True), + ("True", True), + ("1", True), + ], +) +def test_pusher_use_ssl_parsed_from_string(pusher_env, monkeypatch, value, expected): + """PUSHER_USE_SSL is always a string when set via docker-compose/k8s env.""" + monkeypatch.setenv("PUSHER_USE_SSL", value) + client = dependencies.get_pusher_client() + assert client is not None + assert client.kwargs["ssl"] is expected + + +def test_pusher_use_ssl_defaults_to_false(pusher_env): + client = dependencies.get_pusher_client() + assert client is not None + assert client.kwargs["ssl"] is False + + +@pytest.mark.parametrize("value", ["yes", "on", "not-a-bool", ""]) +def test_pusher_use_ssl_unrecognized_value_keeps_ssl_enabled( + pusher_env, monkeypatch, value +): + """Any set-but-unrecognized value enabled SSL before the fix, so keep + SSL on (fail-secure) instead of silently downgrading to plaintext.""" + monkeypatch.setenv("PUSHER_USE_SSL", value) + client = dependencies.get_pusher_client() + assert client is not None + assert client.kwargs["ssl"] is True