From fb527e4ed8a757050bc9d4541319296577478afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Wed, 19 Feb 2020 12:19:51 +0200 Subject: [PATCH] Security: check channel ownership when setting check's channels via API --- CHANGELOG.md | 1 + hc/api/tests/test_update_check.py | 12 ++++++++++++ hc/api/views.py | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee33151c..1e363f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - The "render_docs" command checks if markdown and pygments is installed (#329) - The team size limit is applied to the n. of distinct users across all projects (#332) - Don't let SuspiciousOperation bubble up when validating channel ids in API +- Security: check channel ownership when setting check's channels via API ## v1.13.0 - 2020-02-13 diff --git a/hc/api/tests/test_update_check.py b/hc/api/tests/test_update_check.py index 9cf5c8f4..24b6da63 100644 --- a/hc/api/tests/test_update_check.py +++ b/hc/api/tests/test_update_check.py @@ -157,6 +157,18 @@ class UpdateCheckTestCase(BaseTestCase): self.check.refresh_from_db() self.assertEqual(self.check.channel_set.count(), 0) + def test_it_rejects_channel_from_another_project(self): + charlies_channel = Channel.objects.create(project=self.charlies_project) + + code = str(charlies_channel.code) + r = self.post(self.check.code, {"api_key": "X" * 32, "channels": code}) + + self.assertEqual(r.status_code, 400) + self.assertEqual(r.json()["error"], "invalid channel identifier: " + code) + + self.check.refresh_from_db() + self.assertEqual(self.check.channel_set.count(), 0) + def test_it_rejects_non_uuid_channel_code(self): r = self.post(self.check.code, {"api_key": "X" * 32, "channels": "foo"}) diff --git a/hc/api/views.py b/hc/api/views.py index 827ff9b5..d7662443 100644 --- a/hc/api/views.py +++ b/hc/api/views.py @@ -100,6 +100,7 @@ def _update(check, spec): check.channel_set.clear() else: channels = [] + channel_query = Channel.objects.filter(project=check.project) for chunk in spec["channels"].split(","): try: chunk = uuid.UUID(chunk) @@ -107,8 +108,7 @@ def _update(check, spec): raise BadChannelException("invalid channel identifier: %s" % chunk) try: - channel = Channel.objects.get(code=chunk) - channels.append(channel) + channels.append(channel_query.get(code=chunk)) except Channel.DoesNotExist: raise BadChannelException("invalid channel identifier: %s" % chunk)