Scope report views to the requesting user's authorized products#14870
Open
Maffooch wants to merge 2 commits into
Open
Scope report views to the requesting user's authorized products#14870Maffooch wants to merge 2 commits into
Maffooch wants to merge 2 commits into
Conversation
`product_endpoint_report` (legacy, non-Location branch) built its Endpoint queryset by filtering on `finding__active=True` etc. without restricting to `product=<pid>`, so endpoints (and their findings) from unrelated products appeared in the rendered report. Added `product=product` to the Endpoint filter, and extended `prefetch_related_endpoints_for_report` with an optional `product` parameter so the prefetched Finding queryset is also scoped. While auditing the rest of the module, `report_findings` and `report_endpoints` constructed their initial querysets from `Finding.objects.filter()` / `Endpoint.objects.filter(...)` with no authorization. The rendered output was scoped by the filter wrappers' `qs` property, but moving authorization to the queryset-construction layer (via `get_authorized_findings` / `get_authorized_endpoints` / `get_authorized_locations`) matches the pattern used by `ReportBuilder.get_findings` and removes the implicit reliance on the filter wrapper. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The legacy `product_endpoint_report` branch (and its `Endpoint`-based test fixtures) is unreachable when `V3_FEATURE_LOCATIONS=True`, and the `Endpoint` model raises NotImplementedError in that mode. Mark the regression suite with `@skip_unless_v2` so it only runs against the code path it actually covers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
valentijnscholten
approved these changes
May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three closely-related issues in
dojo/reports/views.pywhere the rendered Endpoint/Finding querysets were not scoped at the queryset-construction layer:product_endpoint_report(real cross-product leak) — the legacy non-Location branch built its Endpoint queryset by filtering onfinding__active=Trueetc. without restricting toproduct=<pid>, so endpoints (and their associated findings) from unrelated products appeared in the rendered report. Addedproduct=productto the Endpoint filter, and extendedprefetch_related_endpoints_for_reportindojo/reports/queries.pywith an optionalproductparameter so the prefetched Finding queryset is also scoped (defense in depth, sinceEndpoint.findingsis an M2M and could in principle link cross-product findings). The widget caller keeps the default — its endpoint set already comes from a filter that the caller is responsible for scoping.report_findings— was constructed fromFinding.objects.filter()(unscoped). The rendered output was nonetheless scoped becauseReportFindingFilter.qscallsget_authorized_findings_for_queryset, but relying on the filter wrapper for authorization is fragile. Moved the authorization to the queryset-construction layer viaget_authorized_findings(Permissions.Finding_View)to match the pattern used byReportBuilder.get_findings.report_endpoints— same pattern as Installation issue #2, swapped toget_authorized_locations(Permissions.Location_View)/get_authorized_endpoints(Permissions.Location_View)so the authorization is visible at the view layer.Added
unittests/test_product_endpoint_report_scoping.pywith two products, each with an engagement / test / active finding / endpoint, and a Reader-on-Product-A-only user:product_endpoint_reporttests check that the report for Product A only contains Product A's unique marker — and confirmed they fail without the queryset fix./reports/findingsand/reports/endpointstests act as behavior locks for the new explicit scoping.Test plan