Skip to content

Commit a088de7

Browse files
authored
Merge pull request #5312 from bjester/code-ql-fixes
Address user-supplied CodeQL issues
2 parents f590deb + 557edf2 commit a088de7

File tree

5 files changed

+30
-26
lines changed

5 files changed

+30
-26
lines changed

contentcuration/contentcuration/urls.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
1. Add an import: from blog import urls as blog_urls
1414
2. Add a URL to urlpatterns: re_path(r'^blog/', include(blog_urls))
1515
"""
16+
import uuid
17+
1618
import django_js_reverse.views as django_js_reverse_views
1719
from django.conf import settings
1820
from django.conf.urls.i18n import i18n_patterns
@@ -53,8 +55,11 @@
5355

5456
class StagingPageRedirectView(RedirectView):
5557
def get_redirect_url(self, *args, **kwargs):
56-
channel_id = kwargs["channel_id"]
57-
return "/channels/{}/#/staging".format(channel_id)
58+
try:
59+
channel_id = uuid.UUID(kwargs["channel_id"]).hex
60+
return "/channels/{}/#/staging".format(channel_id)
61+
except ValueError:
62+
return None
5863

5964

6065
router = routers.DefaultRouter(trailing_slash=False)

contentcuration/contentcuration/utils/files.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,13 @@ def get_thumbnail_encoding(filename, dimension=THUMBNAIL_WIDTH):
108108
inbuffer = default_storage.open(filename, "rb")
109109

110110
else:
111-
inbuffer = open(filename, "rb")
111+
# Normalize the path and ensure it is indeed within STATIC_ROOT
112+
normalized_path = os.path.normpath(filename)
113+
static_root = os.path.abspath(settings.STATIC_ROOT)
114+
abs_path = os.path.abspath(normalized_path)
115+
if not abs_path.startswith(static_root + os.sep):
116+
raise ValueError("Attempted access to file outside of STATIC_ROOT")
117+
inbuffer = open(abs_path, "rb")
112118

113119
if not inbuffer:
114120
raise AssertionError

contentcuration/contentcuration/views/internal.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,9 @@ def api_create_channel_endpoint(request):
221221
"channel_id": obj.pk,
222222
}
223223
)
224-
except KeyError:
224+
except KeyError as e:
225225
return HttpResponseBadRequest(
226-
"Required attribute missing from data: {}".format(data)
226+
"Required attribute missing from data | {}".format(str(e))
227227
)
228228
except Exception as e:
229229
handle_server_error(e, request)
@@ -294,9 +294,9 @@ def api_commit_channel(request):
294294
)
295295
except (Channel.DoesNotExist, PermissionDenied):
296296
return HttpResponseNotFound("No channel matching: {}".format(channel_id))
297-
except KeyError:
297+
except KeyError as e:
298298
return HttpResponseBadRequest(
299-
"Required attribute missing from data: {}".format(data)
299+
"Required attribute missing from data | {}".format(str(e))
300300
)
301301
except Exception as e:
302302
handle_server_error(e, request)
@@ -351,9 +351,9 @@ def api_add_nodes_to_tree(request):
351351
return HttpResponseNotFound("No content matching: {}".format(parent_id))
352352
except ValidationError as e:
353353
return HttpResponseBadRequest(content=str(e))
354-
except KeyError:
354+
except KeyError as e:
355355
return HttpResponseBadRequest(
356-
"Required attribute missing from data: {}".format(data)
356+
"Required attribute missing from data | {}".format(str(e))
357357
)
358358
except NodeValidationError as e:
359359
return HttpResponseBadRequest(str(e))

contentcuration/contentcuration/views/zip.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,7 @@ def get(self, request, zipped_filename, embedded_filepath): # noqa: C901
117117
Handles GET requests and serves a static file from within the zip file.
118118
"""
119119
if not VALID_STORAGE_FILENAME.match(zipped_filename):
120-
return HttpResponseNotFound(
121-
"'{}' is not a valid URL for this zip file".format(zipped_filename)
122-
)
120+
return HttpResponseNotFound("Invalid URL for this zip file")
123121

124122
storage = default_storage
125123

@@ -132,9 +130,7 @@ def get(self, request, zipped_filename, embedded_filepath): # noqa: C901
132130

133131
# if the zipfile does not exist on disk, return a 404
134132
if not storage.exists(zipped_path):
135-
return HttpResponseNotFound(
136-
'"%(filename)s" does not exist in storage' % {"filename": zipped_path}
137-
)
133+
return HttpResponseNotFound("Zipfile does not exist in storage")
138134

139135
# if client has a cached version, use that (we can safely assume nothing has changed, due to MD5)
140136
if request.META.get("HTTP_IF_MODIFIED_SINCE"):
@@ -153,9 +149,7 @@ def get(self, request, zipped_filename, embedded_filepath): # noqa: C901
153149
info = zf.getinfo(embedded_filepath)
154150
except KeyError:
155151
return HttpResponseNotFound(
156-
'"{}" does not exist inside "{}"'.format(
157-
embedded_filepath, zipped_filename
158-
)
152+
"Embedded file does not exist inside zip"
159153
)
160154

161155
# try to guess the MIME type of the embedded file being referenced

contentcuration/kolibri_public/views_v1.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.db.models import TextField
77
from django.db.models import Value
88
from django.http import HttpResponseNotFound
9+
from django.utils.html import escape
910
from django.utils.translation import gettext_lazy as _
1011
from django.views.decorators.cache import cache_page
1112
from kolibri_content.constants.schema_versions import MIN_CONTENT_SCHEMA_VERSION
@@ -75,9 +76,7 @@ def get_public_channel_list(request, version):
7576
try:
7677
channel_list = _get_channel_list(version, request.query_params)
7778
except LookupError:
78-
return HttpResponseNotFound(
79-
_("Api endpoint {} is not available").format(version)
80-
)
79+
return HttpResponseNotFound(_("API version is unavailable"))
8180
return Response(PublicChannelSerializer(channel_list, many=True).data)
8281

8382

@@ -92,12 +91,10 @@ def get_public_channel_lookup(request, version, identifier):
9291
identifier=identifier.strip().replace("-", ""),
9392
)
9493
except LookupError:
95-
return HttpResponseNotFound(
96-
_("Api endpoint {} is not available").format(version)
97-
)
94+
return HttpResponseNotFound(_("API version is unavailable"))
9895
if not channel_list.exists():
9996
return HttpResponseNotFound(
100-
_("No channel matching {} found").format(identifier)
97+
_("No channel matching {} found").format(escape(identifier))
10198
)
10299
return Response(PublicChannelSerializer(channel_list, many=True).data)
103100

@@ -108,7 +105,9 @@ def get_channel_name_by_id(request, channel_id):
108105
""" Endpoint: /public/channels/<channel_id> """
109106
channel = Channel.objects.filter(pk=channel_id).first()
110107
if not channel:
111-
return HttpResponseNotFound("Channel with id {} not found".format(channel_id))
108+
return HttpResponseNotFound(
109+
"Channel with id {} not found".format(escape(channel_id))
110+
)
112111
channel_info = {
113112
"name": channel.name,
114113
"description": channel.description,

0 commit comments

Comments
 (0)