Skip to content

Conversation

dogboat
Copy link
Contributor

@dogboat dogboat commented Sep 10, 2025

This patch introduces v3 text copy. "Product" is renamed to "Asset" and "Product Type" is renamed to "Organization" throughout. Additionally, new URL routes are added to reflect the change (i.e., /asset). A new system setting is added to toggle between the two versions, defaulting to the new copy.

All copy that is altered is concentrated in labels.py, which acts as a sort of centralized directory. A context processor is added allowing templates to reference these values through the labels variable. Application code can similarly access this data through use of the get_labels() method. URL routing is handled by a middleware that checks which version of copy is selected and sets the urlconf accordingly. To that end, a few packages' urls.py have been restructured to support this.

@dogboat
Copy link
Contributor Author

dogboat commented Sep 10, 2025

[sc-11741]

@github-actions github-actions bot added New Migration Adding a new migration file. Take care when merging. settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR apiv2 unittests integration_tests ui labels Sep 10, 2025
Copy link

dryrunsecurity bot commented Sep 10, 2025

DryRun Security

This pull request introduces several information disclosure and authorization issues: it leaks internal IDs and allows membership/group enumeration via specific error messages and filterable sensitive fields (service keys), and it permits privilege escalation by automatically granting organization creators the owner role without requiring the explicit owner-add permission.

Information Disclosure in dojo/object/views.py
Vulnerability Information Disclosure
Description The edit_object function in dojo/object/views.py raises a BadRequest exception when the pid (product ID from the URL) does not match the object_prod.product.id (product ID associated with the tracked file object). The error message constructed for this exception explicitly includes both asset_id (from the URL) and object_asset_id (from the database object). Since BadRequest exceptions are typically returned to the client, an authenticated user with permission to view any product could potentially craft a request to edit_object with a valid pid for a product they can access, and an ttid (tracked file ID) belonging to a different product. This would cause the server to return an error message containing the object_asset_id of the product associated with the ttid, effectively leaking the internal ID of a product they are not authorized to view or edit. While these are internal IDs, their exposure can aid attackers in mapping out the system's data structure and potentially enumerating other product IDs.

msg = labels.ASSET_TRACKED_FILES_ID_MISMATCH_ERROR_MESSAGE % {"asset_id": pid,
"object_asset_id": object_prod.product.id}

Information Disclosure via Error Messages in dojo/organization/api/serializers.py
Vulnerability Information Disclosure via Error Messages
Description The OrganizationMemberSerializer and OrganizationGroupSerializer classes contain validate methods that explicitly check for the existence of a member or group within an organization. If a duplicate entry is found, a ValidationError with the specific message 'Organization Member already exists' or 'Organization Group already exists' is raised. This error message is distinct from permission-related errors (e.g., 'You are not permitted to add a member to this Organization') or errors for non-existent users/groups. An attacker with sufficient privileges to attempt adding members/groups to an organization can use this difference in error messages to enumerate existing members or groups within that organization. By attempting to add a known user/group, the attacker can confirm their membership status based on the returned error message.

msg = "Organization Member already exists"
raise ValidationError(msg)

Information Disclosure via Filterable Service Keys in dojo/asset/api/filters.py
Vulnerability Information Disclosure via Filterable Service Keys
Description The AssetAPIScanConfigurationFilterSet exposes service_key_1, service_key_2, and service_key_3 as filterable fields. These fields are likely to contain sensitive credentials (e.g., API keys). An authenticated user with view permissions on Product_API_Scan_Configuration objects can use these filters to perform a side-channel attack. By querying the API with a guessed service_key value, the attacker can determine if that key exists within any accessible configuration based on whether the API returns data or an empty set. This confirms the validity of a guessed key without direct disclosure of its value.

fields = ("id", "tool_configuration", "service_key_1", "service_key_2", "service_key_3")
class ApiAssetFilter(DojoFilter):

Information Disclosure via Error Messages in dojo/asset/api/serializers.py
Vulnerability Information Disclosure via Error Messages
Description The AssetMemberSerializer and AssetGroupSerializer's validate methods return a specific error message, 'Asset Member already exists' or 'Asset Group already exists', when a user attempts to add a member or group that is already associated with the asset. This distinct error message, compared to other validation errors or permission denied errors, allows an attacker to enumerate existing members or groups for an asset they have access to. For example, if an attacker has permission to manage members of an asset, they can try to add various users. If they receive 'Asset Member already exists', they know that user is already a member. If they receive a different error (e.g., 'User does not exist' or a generic validation error), they know the user is not a member (or doesn't exist).

msg = "Asset Member already exists"
raise ValidationError(msg)

Insufficient Authorization in Organization Creation in dojo/organization/api/views.py
Vulnerability Insufficient Authorization in Organization Creation
Description The perform_create method in OrganizationViewSet automatically assigns the 'owner' role to the user who creates a new organization. This bypasses the explicit permission check (Permissions.Product_Type_Member_Add_Owner) that is required when adding an owner to an existing organization via the OrganizationMemberSerializer. A user with permission to create an organization (Permissions.Product_Type_Add) but without the permission to grant ownership (Permissions.Product_Type_Member_Add_Owner) can exploit this to become an owner of any organization they create, effectively escalating their privileges for that specific entity.

member.role = Role.objects.get(is_owner=True)
member.save()
def destroy(self, request, *args, **kwargs):


All finding details can be found in the DryRun Security Dashboard.

Copy link
Contributor

@mtesauro mtesauro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

@valentijnscholten valentijnscholten changed the title v3 labels Introduce text labels for v3 Sep 12, 2025
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@github-actions github-actions bot removed the New Migration Adding a new migration file. Take care when merging. label Sep 22, 2025
@dogboat dogboat force-pushed the v3_relabel branch 4 times, most recently from 1205a0a to 1013410 Compare September 22, 2025 22:12
@dogboat dogboat requested a review from Maffooch September 23, 2025 16:07
Copy link
Member

@valentijnscholten valentijnscholten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted some comments on the internal slack thread.

@Maffooch Maffooch merged commit 62b53d6 into DefectDojo:dev Oct 2, 2025
88 checks passed
@dogboat dogboat deleted the v3_relabel branch October 2, 2025 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
apiv2 integration_tests settings_changes Needs changes to settings.py based on changes in settings.dist.py included in this PR ui unittests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants