Here is the combined list of vulnerabilities, formatted as markdown and with duplicates removed:
-
Vulnerability Name: Excessive Data Exposure via Include Parameter
-
Description: An attacker can use the
include
query parameter to request inclusion of related resources. If the application does not properly validate or limit the depth and breadth of included resources, or if the serializers for included resources expose more data than intended for the context of the primary resource, it can lead to excessive data exposure. An attacker could potentially retrieve sensitive information from related models that they are not authorized to access directly, simply by crafting a specificinclude
query.- Step-by-step trigger:
- An attacker identifies an API endpoint that uses Django REST framework JSON:API and supports the
include
parameter. - The attacker crafts a GET request to this endpoint with an
include
parameter specifying related resources, potentially including nested relationships (e.g.,include=relation1.relation2
). - The application processes the request and, due to insufficient validation, includes the requested related resources in the response.
- If the serializers for the included resources expose sensitive data and/or there are no authorization checks on included resources, the attacker gains access to data they should not be able to see in the context of the primary resource.
- An attacker identifies an API endpoint that uses Django REST framework JSON:API and supports the
- Step-by-step trigger:
-
Impact: Exposure of sensitive data from related resources. This could include personal information, business secrets, or other confidential data, depending on the models and relationships configured in the application.
-
Vulnerability Rank: High
-
Currently implemented mitigations:
- Validation of include paths against
included_serializers
inIncludedResourcesValidationMixin
in/code/rest_framework_json_api/serializers.py
. This validation ensures that only paths defined inincluded_serializers
are allowed. However, it does not limit depth, breadth, or perform authorization checks on included resources.
- Validation of include paths against
-
Missing mitigations:
- Implement validation and sanitization of the
include
parameter to ensure only allowed relationships are included. (Partially Implemented - path validation exists, but not sufficient) - Implement a configuration to limit the depth and breadth of allowed includes to prevent excessive data retrieval.
- Review and potentially create specialized serializers for included resources that expose only the necessary data when included in a compound document, rather than reusing serializers intended for detailed views of those resources.
- Consider implementing access control checks within the
extract_included
function to ensure the current user is authorized to access the included resources in the context of the primary resource.
- Implement validation and sanitization of the
-
Preconditions:
- Application uses Django REST framework JSON:API and enables the
include
feature. - Application does not have sufficient validation or limitations on the
include
parameter. - Serializers for included resources might expose more data than intended when included in the context of the primary resource.
- Application uses Django REST framework JSON:API and enables the
-
Source code analysis:
-
File:
/code/rest_framework_json_api/renderers.py
-
Function:
JSONRenderer.extract_included
-
Step-by-step analysis:
- The
extract_included
function is called during rendering to process theinclude
query parameter. - It retrieves the
included_resources
from the request andincluded_serializers
from the serializer. - It iterates through the requested
included_resources
. - For each resource, it determines the related instance and serializer.
- It recursively calls
extract_included
for nested resources based on dot notation in theinclude
parameter (e.g.,include=relation1.relation2
). - Vulnerability: There are no explicit checks within
JSONRenderer.extract_included
function to validate if the user is authorized to access the requested included resources. WhileIncludedResourcesValidationMixin
validates if the include path is defined in the serializer, it does not check authorization. The function blindly follows theinclude
parameter and the definedincluded_serializers
, fetching and including data. This allows an attacker to potentially request inclusion of any related resource defined inincluded_serializers
, regardless of whether it's appropriate in the current context or if the user is authorized to access it in this manner.
- The
-
File:
/code/rest_framework_json_api/serializers.py
-
Class:
IncludedResourcesValidationMixin
-
Function:
__init__
-
Step-by-step analysis:
- The
__init__
method ofIncludedResourcesValidationMixin
is called when a serializer using this mixin is initialized. - It retrieves the
include
query parameter from the request usingget_included_resources(request)
. - It iterates through each included resource path.
- For each path, it splits the path by dots to handle nested includes (e.g.,
relation1.relation2
). - It recursively validates each segment of the path against the
included_serializers
defined in the serializer and its nested serializers. - Mitigation (Partial): This mixin does provide a level of validation by ensuring that only include paths that are explicitly defined in
included_serializers
are allowed. If an attacker tries to include a relationship that is not defined inincluded_serializers
, aParseError
is raised, and the request is rejected. - Still Vulnerable: However, this validation is insufficient because it only checks if the path is defined, not if the user is authorized to access the related resources. If a relationship is included in
included_serializers
, it is considered valid for inclusion, even if the user should not have access to the related data in the context of the primary resource. This validation also does not limit the depth or breadth of the include, potentially leading to performance issues and excessive data retrieval if complex include paths are defined.
- The
-
File:
/code/rest_framework_json_api/utils.py
-
Function:
get_included_resources
-
Step-by-step analysis:
- The
get_included_resources
function simply retrieves theinclude
query parameter from the request. - If the parameter is present, it splits the comma-separated values into a list of included resources.
- If the parameter is not present, it attempts to get default included resources from the serializer's
JSONAPIMeta.included_resources
. - No Mitigation: This function does not perform any validation or sanitization of the
include
parameter itself. It only extracts the values from the query parameter.
- The
-
-
Security test case:
- Step 1: Set up a Django REST framework JSON:API application with two models, e.g.,
Article
andAuthor
.Article
has a ForeignKey relationship toAuthor
. - Step 2: Create serializers for
Article
andAuthor
. InArticleSerializer
, defineincluded_serializers = {'author': AuthorSerializer}
and include 'author' inJSONAPIMeta.included_resources
. InAuthorSerializer
, include a field that is considered sensitive, e.g.,email
. Assume that in a normal/authors/{id}
endpoint, theemail
field is protected or not always exposed. - Step 3: Create a viewset for
Article
that usesArticleSerializer
. - Step 4: Send a GET request to the
/articles/
endpoint with theinclude=author
query parameter:GET /articles/?include=author
. - Step 5: Examine the JSON response. Check if the included
author
resources in theincluded
section contain the sensitiveemail
field. - Step 6: If the
email
field is present in the includedauthor
resources, it confirms the excessive data exposure vulnerability. An attacker can use theinclude
parameter to bypass intended data access restrictions and retrieve sensitive information through related resources.
- Step 1: Set up a Django REST framework JSON:API application with two models, e.g.,
-
-
Vulnerability Name: Misconfigured ReadOnlyModelViewSet Allows Write Operations
-
Description: The custom “read‑only” viewset class is derived from DRF’s ReadOnlyModelViewSet but overrides its default allowed HTTP methods to include POST, PATCH, and DELETE. An attacker may send write‑oriented requests (such as POST, PATCH, or DELETE) to an endpoint implemented using this class when the developer intended it to be read‑only.
- Step‑by-step trigger:
- An attacker identifies an endpoint built with ReadOnlyModelViewSet.
- The attacker sends HTTP POST, PATCH, or DELETE requests containing valid JSON:API payloads.
- Due to the permissive method list and lack of strict permission checks, the endpoint processes the request and modifies or deletes data.
- Step‑by-step trigger:
-
Impact: Unauthorized modifications or deletions occur on data that should be immutable, compromising data integrity and violating the principle of least privilege.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- The base class currently lists “get”, “post”, “patch”, “delete”, “head”, and “options” as allowed HTTP methods.
- Custom actions using the
@action
decorator may override behavior, but endpoints built with this base class remain at risk if they assume read‑only behavior.
-
Missing Mitigations:
- Use a stricter default that limits
http_method_names
to only “get”, “head”, and “options” for read‑only endpoints. - Apply additional default permission enforcement on endpoints intended to be read‑only.
- Use a stricter default that limits
-
Preconditions:
- An API endpoint is implemented using the provided
ReadOnlyModelViewSet
without any additional restrictions on HTTP methods or permissions. - The endpoint is publicly accessible.
- An API endpoint is implemented using the provided
-
Source Code Analysis:
- In
/code/rest_framework_json_api/views.py
(and corroborated by tests in/code/tests/views.py
), the customReadOnlyModelViewSet
shows that non‑safe methods are allowed by default. - The design allows developer‑override through custom actions; however, the default behavior is too permissive for endpoints intended only for data retrieval.
- In
-
Security Test Case:
- Deploy an endpoint using
ReadOnlyModelViewSet
without additional method or permission restrictions. - Send an HTTP DELETE request (e.g.
DELETE /some_resource/1/
) with a valid JSON:API payload. - Confirm that the resource is removed.
- Repeat with POST and PATCH requests to verify that write operations are accepted without explicit permission checks.
- Deploy an endpoint using
-
-
Vulnerability Name: Unrestricted CRUD Operations due to Lack of Access Controls
-
Description: Multiple endpoints—including those for blogs, entries, comments, companies, and projects—inherit directly from
ModelViewSet
without specifying any permission classes or access control measures.- Step‑by-step trigger:
- An attacker sends a POST request (for example, to
/blogs/
) with a well‑formed JSON:API payload to create a new resource. - Similarly, the attacker sends PATCH or DELETE requests to endpoints such as
/comments/1/
or/companies/1/
to update or remove records. - With no authentication or authorization checks in place, the operations succeed, allowing unauthorized modifications.
- An attacker sends a POST request (for example, to
- Step‑by-step trigger:
-
Impact: Any unauthorized user can create, modify, or delete resources, leading to potential data integrity, confidentiality, and availability issues.
-
Vulnerability Rank: Critical
-
Currently Implemented Mitigations:
- The project relies on DRF’s default permission model (“AllowAny”) when no explicit permission classes are set on endpoints.
-
Missing Mitigations:
- Implement robust permission classes (e.g.
IsAuthenticated
or custom logic) on all endpoints that allow data modification. - Enforce strict authentication and authorization checks on all modifying endpoints.
- Implement robust permission classes (e.g.
-
Preconditions:
- The application’s endpoints built on
ModelViewSet
(orJsonApiViewSet
without overrides) are deployed publicly without any access control layers.
- The application’s endpoints built on
-
Source Code Analysis:
- In
/code/example/views.py
(and the corresponding URL registrations in/code/example/urls.py
), viewsets such asBlogViewSet
,EntryViewSet
,CommentViewSet
, andCompanyViewSet
expose full CRUD operations without additional restrictions.
- In
-
Security Test Case:
- On a publicly deployed instance, identify an endpoint (e.g.
/blogs/
). - Send a POST request with a valid JSON:API payload to create a new blog resource.
- Verify that the resource is created successfully without requiring authentication.
- Similarly, send PATCH and DELETE requests to other endpoints and confirm that write operations are accepted.
- On a publicly deployed instance, identify an endpoint (e.g.
-
-
Vulnerability Name: Insecure Object Selection in Featured Entry Endpoints
-
Description: The “featured” entry endpoints in
EntryViewSet
andDRFEntryViewSet
override the standardget_object()
method incorrectly. Instead of fetching the record matching the provided primary key, the method uses the URL parameter (named “entry_pk”) to exclude that record and returns the first entry that does not match the given ID.- Step‑by-step trigger:
- An API client sends a GET request to an endpoint such as
/entries/{entry_pk}/
expecting the entry with that specific ID. - The overridden
get_object()
method executes code that excludes the providedentry_pk
and returns the first available entry with a different ID. - The client receives a resource that does not correspond to the requested identifier.
- An API client sends a GET request to an endpoint such as
- Step‑by-step trigger:
-
Impact: This mis‑selection can lead to unintended data exposure and confusion in API response behavior. If business logic relies on a reliable primary key–based lookup, unauthorized data may be disclosed or object‑specific restrictions bypassed.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- A comment in the code (“# Handle featured”) suggests that the override was intended for a “featured” use case but is applied unconditionally whenever the “entry_pk” URL parameter is supplied.
-
Missing Mitigations:
- Correct the object retrieval logic so that when a primary key is specified, the endpoint returns the matching resource.
- If “featured” entries are needed, serve them via a dedicated endpoint with clear and unambiguous logic.
-
Preconditions:
- The endpoint is implemented using
EntryViewSet
orDRFEntryViewSet
and the URL includes an “entry_pk” parameter. - The endpoint is publicly accessible and no custom logic exists to enforce correct object lookup.
- The endpoint is implemented using
-
Source Code Analysis:
- In
/code/example/views.py
, theget_object()
method checks for “entry_pk” inself.kwargs
and, if present, calls:This deviates from the standard lookup usingentry_pk = self.kwargs.get("entry_pk", None) if entry_pk is not None: return Entry.objects.exclude(pk=entry_pk).first()
Entry.objects.get(pk=entry_pk)
, inadvertently returning an unrelated resource.
- In
-
Security Test Case:
- Deploy an endpoint using
EntryViewSet
(orDRFEntryViewSet
) with a URL pattern that includes an “entry_pk” parameter. - Choose a valid primary key (for example, “5”) and send a GET request to
/entries/5/
. - Observe that the returned entry does not have ID 5 but is instead the first entry with a different ID.
- This confirms the retrieval logic is flawed and does not adhere to the expected RESTful behavior.
- Deploy an endpoint using
-
-
Vulnerability Name: DEBUG Mode Enabled in Production Exposes Sensitive Debug Information
-
Description: The application’s configuration (in
/code/example/settings/dev.py
) setsDEBUG = True
and is imported by default via/code/example/settings/__init__.py
. In production, causing an exception (for example, by requesting an undefined URL) will trigger a detailed Django debug page that displays stack traces, environment variables, and configuration settings—including sensitive information.- Step‑by-step trigger:
- An attacker accesses a non‑existent endpoint or deliberately triggers an application error.
- The application, running with
DEBUG = True
, returns a detailed error page with stack trace and configuration details. - The attacker examines the response and extracts sensitive internal information.
- Step‑by-step trigger:
-
Impact: Exposure of internal state, file paths, configuration details, and potentially sensitive data (such as the SECRET_KEY) may help an attacker map the internal structure of the application and plan further attacks.
-
Vulnerability Rank: Critical
-
Currently Implemented Mitigations:
- No mitigation is in place—the settings file explicitly sets
DEBUG = True
.
- No mitigation is in place—the settings file explicitly sets
-
Missing Mitigations:
- Disable debug mode in production by setting
DEBUG = False
. - Configure a custom exception handler that does not expose detailed debug information.
- Disable debug mode in production by setting
-
Preconditions:
- The publicly accessible instance is deployed using the development configuration of settings (i.e. using
/code/example/settings/dev.py
).
- The publicly accessible instance is deployed using the development configuration of settings (i.e. using
-
Source Code Analysis:
- In
/code/example/settings/dev.py
, the lineDEBUG = True
is explicitly set. - Since
/code/example/settings/__init__.py
imports the development settings, no production‑specific override exists, leaving the application in debug mode even if deployed publicly.
- In
-
Security Test Case:
- Deploy the application using the provided settings.
- Access a non‑existent or error‑producing endpoint (for example,
/nonexistent
). - Confirm that the response contains a Django debug page with a full stack trace and internal configuration details such as file paths and environment variables.
- Verify that sensitive data (e.g. SECRET_KEY and database configuration) are exposed on the error page.
-
-
Vulnerability Name: Hardcoded SECRET_KEY in Configuration Allows Forged Signatures
-
Description: The application’s configuration file (
/code/example/settings/dev.py
) contains a hardcoded secret key value ("abc123"
). If an attacker gains knowledge of this secret key—either through accidental code disclosure or via debug error pages—they may use it to forge session cookies or other signed data.- Step‑by-step trigger:
- An attacker discovers the hardcoded
SECRET_KEY
by viewing publicly accessible source code or via a debug page triggered by an error. - Using the known
SECRET_KEY
, the attacker crafts forged session cookies or tampered signed data (such as JSON Web Tokens). - The server, relying on the compromised key for cryptographic signing, accepts the forged data and may allow the attacker to impersonate users or escalate privileges.
- An attacker discovers the hardcoded
- Step‑by-step trigger:
-
Impact: The integrity and authenticity of signed data is compromised, which could lead to session hijacking, unauthorized access to user accounts, and bypass of security controls.
-
Vulnerability Rank: Critical
-
Currently Implemented Mitigations:
- No mitigations are implemented—the
SECRET_KEY
is statically defined in the development settings.
- No mitigations are implemented—the
-
Missing Mitigations:
- Remove hardcoded secret values from the source code and instead load the
SECRET_KEY
securely from environment variables or a dedicated secrets management service.
- Remove hardcoded secret values from the source code and instead load the
-
Preconditions:
- The development settings—which include a hardcoded
SECRET_KEY
—are deployed in the production environment, and the source configuration is either directly accessible or inadvertently exposed (for example, via debug error pages).
- The development settings—which include a hardcoded
-
Source Code Analysis:
- In
/code/example/settings/dev.py
, the lineSECRET_KEY = "abc123"
is hardcoded. - Since
/code/example/settings/__init__.py
importsdev.py
by default, this insecure secret key is used in the deployed application.
- In
-
Security Test Case:
- Examine the deployed application (or trigger an error page via the DEBUG mode vulnerability) to retrieve the
SECRET_KEY
value. - Using the known key
"abc123"
, craft a signed session cookie or token that mimics a valid user session. - Send the forged token to any endpoint that requires authenticated access.
- Verify that the server accepts the forged token, thereby confirming that the signature can be recreated due to the hardcoded secret.
- Examine the deployed application (or trigger an error page via the DEBUG mode vulnerability) to retrieve the
-
-
Vulnerability Name: Inadequate validation of sparse fieldset parameters leading to potential information disclosure
-
Description:
- An attacker crafts a request to a JSON:API endpoint that supports sparse fieldsets.
- The attacker includes the
fields[resource_name]
query parameter with a value that contains special characters or unexpected field names, potentially not corresponding to actual serializer fields. - The
JSONRenderer._filter_sparse_fields
method inrest_framework_json_api/renderers.py
retrieves this value fromrequest.query_params
and splits it by commas without proper validation or sanitization of individual field names. - While the current code iterates through serializer fields and checks for inclusion based on the split
sparse_fields
, inadequate validation ofsparse_fields
values could lead to unexpected behavior if a crafted value bypasses intended filtering, potentially exposing more data than intended or causing backend errors. - Although direct injection into field names seems limited by the serializer's field definitions, the lack of validation on the input
sparse_fieldset_value
itself is a potential vulnerability. It could be exploited if future code changes or specific serializer configurations introduce weaknesses when handling these unfiltered field names.
- Step-by-step trigger:
- An attacker identifies a JSON:API endpoint supporting sparse fieldsets.
- The attacker crafts a GET request with the
fields[resource_name]
query parameter. - The value of this parameter includes invalid field names or special characters.
- The server processes the request without validating the
fields[resource_name]
value. - Although current filtering might prevent immediate data exposure, the lack of validation is a vulnerability that could be exploited in the future.
-
Impact: Potential information disclosure. While the immediate risk might be low due to the current field filtering logic, inadequate validation opens the door for future vulnerabilities or unexpected behavior that could lead to exposing sensitive data if field filtering is bypassed or if backend errors expose information.
-
Vulnerability Rank: High
-
Currently Implemented Mitigations:
- None: The code retrieves and processes the
fields[resource_name]
query parameter without any explicit validation of the field names provided.
- None: The code retrieves and processes the
-
Missing Mitigations:
- Input validation: Implement robust validation for the
fields[resource_name]
query parameter to ensure that only valid field names for the given resource are accepted. This validation should occur inJSONRenderer._filter_sparse_fields
before splitting and using the field names. - Sanitization: Sanitize the input field names to remove any potentially malicious characters or unexpected input.
- Input validation: Implement robust validation for the
-
Preconditions:
- The API endpoint must be using
rest_framework_json_api.renderers.JSONRenderer
. - The API endpoint must support sparse fieldsets.
- The application must be deployed publicly and accessible to external attackers.
- The API endpoint must be using
-
Source Code Analysis:
File: /code/rest_framework_json_api/renderers.py
@classmethod def _filter_sparse_fields(cls, serializer, fields, resource_name): request = serializer.context.get("request") if request: sparse_fieldset_query_param = f"fields[{resource_name}]" sparse_fieldset_value = request.query_params.get( sparse_fieldset_query_param ) if sparse_fieldset_value is not None: # <-- Input from query parameter is used without validation sparse_fields = sparse_fieldset_value.split(",") # <-- Input is split by comma without validation return { field_name: field for field_name, field, in fields.items() if field.field_name in sparse_fields # <-- Filtering logic based on unvalidated input # URL field is not considered a field in JSON:API spec # but a link so need to keep it or ( field.field_name == api_settings.URL_FIELD_NAME and isinstance(field, relations.HyperlinkedIdentityField) ) } return fields
- The
_filter_sparse_fields
method retrieves thefields[resource_name]
query parameter value directly fromrequest.query_params
without validation. - It then splits this value by commas to create a list of
sparse_fields
. - The code iterates through the serializer's
fields
and includes a field in the output only if itsfield.field_name
is present in thesparse_fields
list or if it's the URL field. - The vulnerability lies in the lack of validation of
sparse_fieldset_value
. An attacker could potentially inject crafted values here. While the current filtering logic might limit immediate exploitation, it's a risky pattern.
- The
-
Security Test Case:
- Send a GET request to a JSON:API endpoint that supports sparse fieldsets (e.g.,
/blogs/
). - Include the
fields[Blog]
query parameter with an invalid or unexpected value, for example:fields[Blog]=name,invalid-field,name
. - Observe the response. While in the current implementation it might not directly expose extra data due to the field check against serializer fields, a lack of validation is present.
- To enhance the test case for future potential vulnerabilities, try injecting special characters or very long strings in
fields[Blog]
to observe if it causes any backend errors or unexpected behavior that might indicate a deeper issue related to how unvalidated input is handled. For example:fields[Blog]=name,very-long-field-name-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
. - Examine the server-side logs for any errors or warnings related to processing the crafted
fields[Blog]
parameter. While a successful exploit might not be immediately apparent due to current filtering, the lack of validation is a vulnerability that should be addressed to prevent future exploits or unexpected behavior arising from input injection.
- Send a GET request to a JSON:API endpoint that supports sparse fieldsets (e.g.,
-