CVE-2026-34406
An authorization flaw in APTRS allows users to become a superuser via the API.
- CVSS 9.4
- CWE-915
- Authentication, Authorization, and Session Management
- Remote
APTRS (Automated Penetration Testing Reporting System) is a Python and Django-based automated reporting tool designed for penetration testers and security organizations. Prior to version 2.0.1, the edit_user endpoint (POST /api/auth/edituser/<pk>) allows Any user who can reach that endpoint and submit crafted permission to escalate their own account (or any other account) to superuser by including "is_superuser": true in the request body. The root cause is that CustomUserSerializer explicitly includes is_superuser in its fields list but omits it from read_only_fields, making it a writable field. The edit_user view performs no additional validation to prevent non-superusers from modifying this field. Once is_superuser is set to true, gaining unrestricted access to all application functionality without requiring re-authentication. This issue has been patched in version 2.0.1.
- CWE
- CWE-915
- CVSS base score
- 9.4
- Published
- 2026-03-31
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Authentication, Authorization, and Session Management
- Subcategory
- Privilege Escalation
- Accessibility scope
- Remote
- Impact
- Privilege Escalation
- Affected component
- APTRS
- Fixed by upgrading
- Yes
Solution
Upgrade APTRS to version 2.0.1 or later.
Vulnerable code sample
# In a file like aplication/serializers.py
# Note: This code is a representation of the described vulnerability.
from django.contrib.auth.models import User
from rest_framework import serializers
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
'id',
'username',
'first_name',
'last_name',
'email',
'is_staff',
'is_active',
'is_superuser', # The vulnerable field
'last_login',
'date_joined'
]
# The 'is_superuser' field is critically missing from read_only_fields,
# making it writable through the API.
read_only_fields = [
'last_login',
'date_joined'
]
# In a file like application/views.py
# Note: This code is a representation of the described vulnerability.
from django.contrib.auth.models import User
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
# from .serializers import CustomUserSerializer # Assumed import
class EditUserView(APIView):
"""
Allows editing a user's details.
Vulnerable because it uses CustomUserSerializer without any further
validation on who can modify sensitive fields like 'is_superuser'.
"""
permission_classes = [IsAuthenticated] # Any authenticated user can access this.
def post(self, request, pk):
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return Response(
{"error": "User not found."},
status=status.HTTP_404_NOT_FOUND
)
# The serializer allows 'is_superuser' to be set from request.data
serializer = CustomUserSerializer(user, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# In a file like application/urls.py
# Note: This code is a representation of the described vulnerability.
from django.urls import path
# from .views import EditUserView # Assumed import
urlpatterns = [
# The vulnerable endpoint
path('api/auth/edituser/<int:pk>', EditUserView.as_view(), name='edit-user'),
]Patched code sample
from django.contrib.auth import get_user_model
from rest_framework import serializers
User = get_user_model()
class CustomUserSerializer(serializers.ModelSerializer):
"""
Serializer for the User model.
The 'is_superuser' field is explicitly made read-only to prevent
privilege escalation by non-admin users, addressing CVE-2026-34406.
"""
class Meta:
model = User
fields = (
'id',
'username',
'email',
'first_name',
'last_name',
'is_staff',
'is_superuser',
)
# FIX: By adding 'is_superuser' to read_only_fields, the serializer
# will ignore this field in the input data during create or update
# operations. This prevents any user from modifying their own or another
# user's superuser status via the API endpoint.
read_only_fields = ('is_superuser', 'is_staff')Payload
{
"is_superuser": true
}
Cite this entry
@misc{vaitp:cve202634406,
title = {{An authorization flaw in APTRS allows users to become a superuser via the API.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-34406},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-34406/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
