Skip to content

fix(issues): Enforce project access on event ID lookup endpoint#115784

Merged
oioki merged 2 commits into
masterfrom
fix/eventid-team-access
May 19, 2026
Merged

fix(issues): Enforce project access on event ID lookup endpoint#115784
oioki merged 2 commits into
masterfrom
fix/eventid-team-access

Conversation

@oioki
Copy link
Copy Markdown
Member

@oioki oioki commented May 19, 2026

The EventIdLookupEndpoint (GET /api/0/organizations/{org}/eventids/{event_id}/) inherits from OrganizationEndpoint, whose permission class only checks organization membership. The handler then queried Project.objects.filter(organization=organization) directly — every project in the org — and used that as the search scope for the eventstore lookup. As a result, any org member could resolve an event ID from a project whose owning team they were not on, including the case of a team member whose access was revoked but who retained event IDs collected during prior legitimate access. The sibling ShortIdLookupEndpoint already enforces project-level access via GroupPermissionProjectPermission.has_object_permission; the eventid endpoint did not.

This switches the project lookup to self.get_projects(request, organization, include_all_accessible=True). include_all_accessible keeps the previous behaviour for org owners, managers, staff, and superusers (their global scope returns True from has_project_access for every org project) while applying has_project_access per project for everyone else. An early ResourceDoesNotExist is raised when the caller has access to no projects in the org, since the previous handler would otherwise pass an empty project_ids list to Snuba and surface as an UnqualifiedQueryError (500).

Adds a regression test mirroring test_access_non_member_project on the shortid endpoint: org member, allow_joinleave=False, no team memberships, expects 404 on event-id lookup.

Fixes VULN-52

The eventids endpoint inherits from OrganizationEndpoint, whose permission
class only checks organization membership. The handler then iterated every
project in the organization, bypassing the project-level team-access check
that sibling endpoints (e.g. shortid lookup) apply. An org member who is
not on a project's owning team could resolve any event ID from that
project, returning the full event payload — including the case of a team
member whose access was revoked but who retained event IDs from prior
legitimate access.

Route the project lookup through get_projects(..., include_all_accessible
=True) so the eventstore search is scoped to projects the caller can
access. include_all_accessible preserves the previous behaviour for org
owners, managers, and superusers (their global scope grants access to
every org project) while applying has_project_access for everyone else.
Return 404 when the caller has access to no projects in the org so the
empty project_ids list does not reach Snuba as an UnqualifiedQueryError.
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 19, 2026

VULN-52

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 19, 2026
@oioki oioki marked this pull request as ready for review May 19, 2026 12:43
@oioki oioki requested review from a team as code owners May 19, 2026 12:44

def test_access_non_member_project(self) -> None:
# Org member who is not on the project's owning team must not be able
# to resolve event IDs from that project, even with Open Membership off.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

might be worth adding a test that with open membership on, you can access projects you don't access.

Add a regression test verifying that with Open Membership on (the default),
an org member who is not on the project's owning team can still resolve
event IDs from that project. This pins down the intended product behaviour
so a future tightening of the endpoint does not accidentally break it.
@oioki oioki enabled auto-merge (squash) May 19, 2026 16:23
@oioki oioki merged commit e76c88b into master May 19, 2026
62 checks passed
@oioki oioki deleted the fix/eventid-team-access branch May 19, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants