mirror of
https://github.com/zulip/zulip.git
synced 2025-11-05 14:35:27 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
726ab9c4fa | ||
|
|
b7c87a4d82 |
@@ -52,7 +52,7 @@ author = 'The Zulip Team'
|
|||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = '2.0'
|
version = '2.0'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = '2.0.7'
|
release = '2.0.8'
|
||||||
|
|
||||||
# This allows us to insert a warning that appears only on an unreleased
|
# This allows us to insert a warning that appears only on an unreleased
|
||||||
# version, e.g. to say that something is likely to have changed.
|
# version, e.g. to say that something is likely to have changed.
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ All notable changes to the Zulip server are documented in this file.
|
|||||||
This section lists notable unreleased changes; it is generally updated
|
This section lists notable unreleased changes; it is generally updated
|
||||||
in bursts.
|
in bursts.
|
||||||
|
|
||||||
|
### 2.0.8 -- 2019-12-12
|
||||||
|
|
||||||
|
- CVE-2019-19775: Close open redirect in thumbnail view.
|
||||||
|
|
||||||
### 2.0.7 -- 2019-11-21
|
### 2.0.7 -- 2019-11-21
|
||||||
|
|
||||||
- CVE-2019-18933: Fix insecure account creation via social authentication.
|
- CVE-2019-18933: Fix insecure account creation via social authentication.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ZULIP_VERSION = "2.0.7"
|
ZULIP_VERSION = "2.0.8"
|
||||||
LATEST_MAJOR_VERSION = "2.0"
|
LATEST_MAJOR_VERSION = "2.0"
|
||||||
LATEST_RELEASE_VERSION = "2.0.7"
|
LATEST_RELEASE_VERSION = "2.0.8"
|
||||||
LATEST_RELEASE_ANNOUNCEMENT = "https://blog.zulip.org/2019/03/01/zulip-2-0-released/"
|
LATEST_RELEASE_ANNOUNCEMENT = "https://blog.zulip.org/2019/03/01/zulip-2-0-released/"
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import markdown
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
import urllib
|
import urllib
|
||||||
|
import urllib.parse
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import html
|
import html
|
||||||
@@ -553,7 +554,7 @@ class InlineHttpsProcessor(markdown.treeprocessors.Treeprocessor):
|
|||||||
found_imgs = walk_tree(root, lambda e: e if e.tag == "img" else None)
|
found_imgs = walk_tree(root, lambda e: e if e.tag == "img" else None)
|
||||||
for img in found_imgs:
|
for img in found_imgs:
|
||||||
url = img.get("src")
|
url = img.get("src")
|
||||||
if not url.startswith("http://"):
|
if urllib.parse.urlsplit(url).scheme != "http":
|
||||||
# Don't rewrite images on our own site (e.g. emoji).
|
# Don't rewrite images on our own site (e.g. emoji).
|
||||||
continue
|
continue
|
||||||
img.set("src", get_camo_url(url))
|
img.set("src", get_camo_url(url))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import base64
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import urllib
|
import urllib
|
||||||
|
from urllib.parse import urljoin, urlsplit, urlunsplit
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from libthumbor import CryptoURL
|
from libthumbor import CryptoURL
|
||||||
|
|
||||||
@@ -19,7 +20,8 @@ def is_thumbor_enabled() -> bool:
|
|||||||
return settings.THUMBOR_URL != ''
|
return settings.THUMBOR_URL != ''
|
||||||
|
|
||||||
def user_uploads_or_external(url: str) -> bool:
|
def user_uploads_or_external(url: str) -> bool:
|
||||||
return url.startswith('http') or url.lstrip('/').startswith('user_uploads/')
|
u = urlsplit(url)
|
||||||
|
return u.scheme != "" or u.netloc != "" or u.path.startswith("/user_uploads/")
|
||||||
|
|
||||||
def get_source_type(url: str) -> str:
|
def get_source_type(url: str) -> str:
|
||||||
if not url.startswith('/user_uploads/'):
|
if not url.startswith('/user_uploads/'):
|
||||||
@@ -33,16 +35,16 @@ def get_source_type(url: str) -> str:
|
|||||||
def generate_thumbnail_url(path: str,
|
def generate_thumbnail_url(path: str,
|
||||||
size: str='0x0',
|
size: str='0x0',
|
||||||
is_camo_url: bool=False) -> str:
|
is_camo_url: bool=False) -> str:
|
||||||
if not (path.startswith('https://') or path.startswith('http://')):
|
path = urljoin("/", path)
|
||||||
path = '/' + path
|
u = urlsplit(path)
|
||||||
|
|
||||||
if not is_thumbor_enabled():
|
if not is_thumbor_enabled():
|
||||||
if path.startswith('http://'):
|
if u.scheme == "" and u.netloc == "":
|
||||||
return get_camo_url(path)
|
return urlunsplit(u)
|
||||||
return path
|
return get_camo_url(path)
|
||||||
|
|
||||||
if not user_uploads_or_external(path):
|
if u.scheme == "" and u.netloc == "" and not u.path.startswith("/user_uploads/"):
|
||||||
return path
|
return urlunsplit(u)
|
||||||
|
|
||||||
source_type = get_source_type(path)
|
source_type = get_source_type(path)
|
||||||
safe_url = base64.urlsafe_b64encode(path.encode()).decode('utf-8')
|
safe_url = base64.urlsafe_b64encode(path.encode()).decode('utf-8')
|
||||||
|
|||||||
@@ -148,6 +148,9 @@ class ThumbnailTest(ZulipTestCase):
|
|||||||
image_url = 'http://images.foobar.com/12345'
|
image_url = 'http://images.foobar.com/12345'
|
||||||
run_test_with_image_url(image_url)
|
run_test_with_image_url(image_url)
|
||||||
|
|
||||||
|
image_url = '//images.foobar.com/12345'
|
||||||
|
run_test_with_image_url(image_url)
|
||||||
|
|
||||||
def test_local_file_type(self) -> None:
|
def test_local_file_type(self) -> None:
|
||||||
def get_file_path_urlpart(uri: str, size: str='') -> str:
|
def get_file_path_urlpart(uri: str, size: str='') -> str:
|
||||||
url_in_result = 'smart/filters:no_upscale()%s/%s/source_type/local_file'
|
url_in_result = 'smart/filters:no_upscale()%s/%s/source_type/local_file'
|
||||||
@@ -281,7 +284,8 @@ class ThumbnailTest(ZulipTestCase):
|
|||||||
with self.settings(THUMBOR_URL=''):
|
with self.settings(THUMBOR_URL=''):
|
||||||
result = self.client_get("/thumbnail?url=%s&size=full" % (quoted_uri))
|
result = self.client_get("/thumbnail?url=%s&size=full" % (quoted_uri))
|
||||||
self.assertEqual(result.status_code, 302, result)
|
self.assertEqual(result.status_code, 302, result)
|
||||||
self.assertEqual(uri, result.url)
|
base = 'https://external-content.zulipcdn.net/external_content/56c362a24201593891955ff526b3b412c0f9fcd2/68747470733a2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67'
|
||||||
|
self.assertEqual(base, result.url)
|
||||||
|
|
||||||
uri = 'http://www.google.com/images/srpr/logo4w.png'
|
uri = 'http://www.google.com/images/srpr/logo4w.png'
|
||||||
quoted_uri = urllib.parse.quote(uri, safe='')
|
quoted_uri = urllib.parse.quote(uri, safe='')
|
||||||
@@ -291,6 +295,14 @@ class ThumbnailTest(ZulipTestCase):
|
|||||||
base = 'https://external-content.zulipcdn.net/external_content/7b6552b60c635e41e8f6daeb36d88afc4eabde79/687474703a2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67'
|
base = 'https://external-content.zulipcdn.net/external_content/7b6552b60c635e41e8f6daeb36d88afc4eabde79/687474703a2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67'
|
||||||
self.assertEqual(base, result.url)
|
self.assertEqual(base, result.url)
|
||||||
|
|
||||||
|
uri = '//www.google.com/images/srpr/logo4w.png'
|
||||||
|
quoted_uri = urllib.parse.quote(uri, safe='')
|
||||||
|
with self.settings(THUMBOR_URL=''):
|
||||||
|
result = self.client_get("/thumbnail?url=%s&size=full" % (quoted_uri,))
|
||||||
|
self.assertEqual(result.status_code, 302, result)
|
||||||
|
base = 'https://external-content.zulipcdn.net/external_content/676530cf4b101d56f56cc4a37c6ef4d4fd9b0c03/2f2f7777772e676f6f676c652e636f6d2f696d616765732f737270722f6c6f676f34772e706e67'
|
||||||
|
self.assertEqual(base, result.url)
|
||||||
|
|
||||||
def test_with_different_THUMBOR_URL(self) -> None:
|
def test_with_different_THUMBOR_URL(self) -> None:
|
||||||
self.login(self.example_email("hamlet"))
|
self.login(self.example_email("hamlet"))
|
||||||
fp = StringIO("zulip!")
|
fp = StringIO("zulip!")
|
||||||
|
|||||||
Reference in New Issue
Block a user