Skip to content

Commit 7ecda1a

Browse files
committed
streams: Fix autosubscribe security bug (CVE-2017-0881).
A bug in Zulip's implementation of the "stream exists" endpoint meant that any user of a Zulip server could subscribe to an invite-only stream without needing to be invited by using the "autosubscribe" argument. Thanks to Rafid Aslam for discovering this issue.
1 parent 7e0ce22 commit 7ecda1a

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

Diff for: zerver/tests/test_subs.py

+23
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,29 @@ def test_existing_subscriptions_autosubscription(self):
19361936
self.assertIn("exists", json)
19371937
self.assertTrue(json["exists"])
19381938

1939+
def test_existing_subscriptions_autosubscription_private_stream(self):
1940+
# type: () -> None
1941+
"""Call /json/subscriptions/exist on an existing private stream with
1942+
autosubscribe should fail.
1943+
"""
1944+
stream_name = "Saxony"
1945+
result = self.common_subscribe_to_streams("cordelia@zulip.com", [stream_name],
1946+
invite_only=True)
1947+
stream = get_stream(stream_name, self.realm)
1948+
1949+
result = self.client_post("/json/subscriptions/exists",
1950+
{"stream": stream_name, "autosubscribe": True})
1951+
self.assert_json_success(result)
1952+
json = ujson.loads(result.content)
1953+
self.assertIn("exists", json)
1954+
self.assertTrue(json["exists"])
1955+
self.assertIn("subscribed", json)
1956+
# Importantly, we are not now subscribed
1957+
self.assertFalse(json["subscribed"])
1958+
self.assertEqual(Subscription.objects.filter(
1959+
recipient__type=Recipient.STREAM,
1960+
recipient__type_id=stream.id).count(), 1)
1961+
19391962
def get_subscription(self, user_profile, stream_name):
19401963
# type: (UserProfile, Text) -> Subscription
19411964
stream = get_stream(stream_name, self.realm)

Diff for: zerver/views/streams.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ def stream_exists_backend(request, user_profile, stream_id, autosubscribe):
481481
result = {"exists": bool(stream)}
482482
if stream is not None:
483483
recipient = get_recipient(Recipient.STREAM, stream.id)
484-
if autosubscribe:
484+
if not stream.invite_only and autosubscribe:
485485
bulk_add_subscriptions([stream], [user_profile])
486486
result["subscribed"] = is_active_subscriber(
487487
user_profile=user_profile,

0 commit comments

Comments
 (0)