CVE-2023-5498 (published 2023-10-10T10:15Z)

Cross-Site Request Forgery (CSRF) in GitHub repository chiefonboarding/chiefonboarding prior to v2.0.47.

CVSS v3 base score: 4.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/chiefonboarding/chiefonboarding
commit_details: repo_url: https://github.com/chiefonboarding/chiefonboarding
author: Stan Triepels
author_date: 2023-10-02 23:31:06+02:00
msg: Fix missing csrf token on admin task done view (#367)
repository: repo_url: https://github.com/chiefonboarding/chiefonboarding
repo_name: chiefonboarding/ChiefOnboarding
description: Free and open-source employee onboarding platform. Onboard new hires through Slack or the web portal.
repo_language: Python
owner: chiefonboarding
file_changes: filename: admin_tasks_detail.html
change_type: ModificationType.MODIFY
diff: @@ -2,13 +2,16 @@
 {% load i18n %}
 {% load crispy_forms_tags %}
 {% block actions %}
-<a type="submit" href="{% url 'admin_tasks:completed' object.id %}" class="btn btn-primary">
-  {% if object.completed %}
-    {% translate "Reopen" %}
-  {% else %}
-    {% translate "Complete" %}
-  {% endif %}
-</a>
+<form method="post" action="{% url 'admin_tasks:completed' object.id %}">
+  {% csrf_token %}
+  <button type="submit" class="btn btn-primary">
+    {% if object.completed %}
+      {% translate "Reopen" %}
+    {% else %}
+      {% translate "Complete" %}
+    {% endif %}
+  </button>
+</form>
 {% endblock %}
 
 {% block content %}

programming_language: HTML
filename: tests.py
change_type: ModificationType.MODIFY
diff: @@ -292,7 +292,7 @@ def test_complete_admin_task(client, admin_factory, admin_task_factory):
     assert "Complete" in response.content.decode()
     assert complete_url in response.content.decode()
 
-    response = client.get(complete_url, follow=True)
+    response = client.post(complete_url, follow=True)
     task1.refresh_from_db()
     task2.refresh_from_db()
 

programming_language: Python
filename: views.py
change_type: ModificationType.MODIFY
diff: @@ -1,9 +1,10 @@
 from django.contrib.messages.views import SuccessMessageMixin
 from django.http import Http404
-from django.shortcuts import get_object_or_404
+from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse, reverse_lazy
 from django.utils.translation import gettext as _
-from django.views.generic.base import RedirectView
+
+from django.views.generic.detail import BaseDetailView
 from django.views.generic.edit import CreateView, UpdateView
 from django.views.generic.list import ListView
 
@@ -45,16 +46,14 @@ class AllAdminTasksListView(LoginRequiredMixin, ManagerPermMixin, ListView):
         return context
 
 
-class AdminTaskToggleDoneView(LoginRequiredMixin, ManagerPermMixin, RedirectView):
-    permanent = False
-    pattern_name = "admin_tasks:detail"
+class AdminTaskToggleDoneView(LoginRequiredMixin, ManagerPermMixin, BaseDetailView):
+    model = AdminTask
 
-    def get(self, request, *args, **kwargs):
-        task_id = self.kwargs.get("pk", -1)
-        admin_task = get_object_or_404(AdminTask, id=task_id)
+    def post(self, request, *args, **kwargs):
+        admin_task = self.get_object()
         admin_task.completed = not admin_task.completed
         admin_task.save()
-        return super().get(request, *args, **kwargs)
+        return redirect("admin_tasks:detail", pk=admin_task.id)
 
 
 class AdminTasksCreateView(

programming_language: Python