You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2026/10/06 14:14:24 UTC
(tooling-trusted-releases) branch sbp updated: Disallow PubSub redirects to prevent downgrade to HTTP
This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/sbp by this push:
new 3adc33f1 Disallow PubSub redirects to prevent downgrade to HTTP
3adc33f1 is described below
commit 3adc33f18ccad0f1acb047878eb38c83d8638dbc
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Tue Oct 6 15:13:30 2026 +0100
Disallow PubSub redirects to prevent downgrade to HTTP
---
atr/pubsub.py | 4 +++-
tests/unit/test_pubsub.py | 13 +++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/atr/pubsub.py b/atr/pubsub.py
index 509c93b5..92a66cc6 100644
--- a/atr/pubsub.py
+++ b/atr/pubsub.py
@@ -177,9 +177,11 @@ async def _handle_payload(payload: dict[str, Any]) -> str | None:
async def _process_connection(session, pubsub_url, since):
# Connect to pubsub and listen for payloads.
headers = {"X-Fetch-Since-Cursor": since} if since else {}
- async with session.get(pubsub_url, headers=headers) as conn:
+ async with session.get(pubsub_url, headers=headers, allow_redirects=False) as conn:
# print('LIMITS:', conn.content.get_read_buffer_limits())
conn.raise_for_status()
+ if 300 <= conn.status < 400:
+ raise ValueError(f"PubSub redirects are not allowed (HTTP {conn.status})")
if conn.content_type != _STREAM_CONTENT_TYPE:
log.warning(f"Unexpected pubsub content type: {conn.content_type}")
if since:
diff --git a/tests/unit/test_pubsub.py b/tests/unit/test_pubsub.py
index b9680ff8..e25fcc56 100644
--- a/tests/unit/test_pubsub.py
+++ b/tests/unit/test_pubsub.py
@@ -20,6 +20,7 @@ import json
import pathlib
from typing import Any
+import aiohttp
import aiohttp.web as web
import pytest
@@ -33,6 +34,7 @@ class Server:
def __init__(self) -> None:
self.connections = 0
self.cursors: list[str | None] = []
+ self.redirect = 0
self.reject = 0
self.scripts: list[list[bytes]] = []
self.url = ""
@@ -40,6 +42,8 @@ class Server:
async def handle(self, request: web.Request) -> web.StreamResponse:
self.connections += 1
self.cursors.append(request.headers.get("X-Fetch-Since-Cursor"))
+ if self.redirect:
+ return web.Response(status=self.redirect, headers={"Location": self.url}, body=_line(_EVENT))
if self.reject > 0:
self.reject -= 1
return web.Response(status=503)
@@ -125,6 +129,15 @@ async def test_listen_yields_events_and_keepalives(server: Server) -> None:
assert server.connections == 1
+@pytest.mark.parametrize("status", [301, 302, 303, 307, 308])
+async def test_process_connection_rejects_redirects(server: Server, status: int) -> None:
+ server.redirect = status
+ async with aiohttp.ClientSession(auth=aiohttp.BasicAuth("test", "test")) as session:
+ with pytest.raises(ValueError, match="PubSub redirects are not allowed"):
+ await anext(pubsub._process_connection(session, server.url, None))
+ assert server.connections == 1
+
+
async def test_start_checkpoints_at_keepalives(monkeypatch: pytest.MonkeyPatch) -> None:
saves: list[tuple[str, str]] = []
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org