Jun 6, 2026·7 min read·4 visits
Authenticated users can bypass project boundaries to view unauthorized event data (stack traces, variables, breadcrumbs) by providing target event UUIDs directly to issue URL parameters due to a lack of scope enforcement in the Django query logic.
An Insecure Direct Object Reference (IDOR) vulnerability in Bugsink (versions < 2.2.0) allows authenticated users with access to at least one project to view sensitive event details (including stack traces, local/environment variables, and execution breadcrumbs) belonging to other projects, by supplying a known event UUID directly to the issue event URL paths.
Bugsink is an open-source, self-hosted error tracking application designed to serve as a lightweight, drop-in alternative to Sentry. The platform monitors applications, captures diagnostic telemetry, and aggregates runtime errors to assist software developers and security engineers in tracking application crashes.
In versions of Bugsink prior to 2.2.0, an architectural isolation failure existed between projects managed within the same installation. The application did not enforce project-level authorization boundaries when processing queries for individual issue events. An authenticated user possessing access to a single project could access private, unmasked diagnostic reports belonging to other, completely unrelated projects.
This vulnerability falls under the class of Insecure Direct Object Reference (IDOR) or Broken Object Level Authorization (BOLA), tracked as CWE-639. The flaw specifically surfaces in the issue-event detail views, exposing high-entropy debug data like stack traces, variable values, local environments, and system logs to any authenticated agent who can obtain a target event's unique identifier.
The architecture of Bugsink organizes error data hierarchically across three main database abstractions: Projects, Issues, and Events. A Project acts as the primary logical boundary for tenant isolation. An Issue represents a logical grouping of distinct but identical occurrences, while an Event records the specific, atomic instance of a runtime error.
The routing rules configured for querying details of an event utilized URLs structured with both the group identifier (the issue ID) and the specific event identifier (the event primary key). For example, a request to retrieve runtime details routed through /issues/issue/<issue_id>/event/<event_pk>/details/ would instruct the backend to load the target resources.
The core flaw resided in the backend implementation of the Django view layer helper function _get_event in issues/views.py. Although the application correctly checked that the requesting user had access rights to the <issue_id> variable specified in the URL path, it did not utilize that context when querying the database for the event object. Instead, the server invoked a global Event.objects.get(pk=event_pk) database lookup, completely ignoring the associated project and issue foreign key restraints during retrieval.
This implementation allowed an attacker to reference a valid, authorized issue ID alongside an arbitrary, unauthorized event identifier in the HTTP query path. Because the database engine resolved the event globally, it successfully retrieved and rendered data across isolation boundaries, rendering tenant separation mechanisms ineffective.
To understand the exact programmatic root cause, we must analyze the Django database query routine before and after the patch. The vulnerability existed in the _get_event view helper function which processed requests for stacktraces, details, and breadcrumbs.
# Vulnerable implementation in issues/views.py
def _get_event(qs, issue, event_pk, digest_order, nav, bounds):
# ...
elif event_pk is not None:
# we match on both internal and external id, trying internal first
try:
# BUG: Global database query with no scoping parameters
return Event.objects.get(pk=event_pk)
except Event.DoesNotExist:
# we match on external id "for user ergonomics"
return Event.objects.get(project=issue.project, event_id=event_pk)In the vulnerable implementation, the fallback exception block attempted to scope queries using project=issue.project, but the initial try block returned the database object globally when queried via primary key. The security patch introduced in commit 9128661cc4500e2ddbe4ef47fddffa6796dfbe58 corrected this behavior by scoping all primary key queries to the specific authorized issue context.
# Patched implementation in issues/views.py
def _get_event(qs, issue, event_pk, digest_order, nav, bounds):
# ...
elif event_pk is not None:
# we match on both internal and external id, trying internal first
try:
# FIX: Scopes the primary key query to the validated issue
return Event.objects.get(issue=issue, pk=event_pk)
except Event.DoesNotExist:
# we match on external id "for user ergonomics"; notes as in `event_by_id` apply, except for the fact that
# in this case we have the project available, guaranteeing uniqueness & fast lookup.
# FIX: Restricts fallback queries to both the authorized project and issue context
return Event.objects.get(project=issue.project, issue=issue, event_id=event_pk)The fix is robust and complete for this specific code path. By binding both queries to the validated issue parameter, the application ensures that an event is only returned if it belongs to the exact issue context that the user is authorized to access, preventing any cross-project leakage.
Exploiting this vulnerability requires the attacker to possess authenticated access to at least one legitimate project on the target Bugsink instance. It also requires the attacker to obtain a valid target Event UUID from an unauthorized project, as the platform generates high-entropy, cryptographically secure 128-bit UUIDs for event tracking.
Because of the extreme difficulty of brute-forcing UUIDs, the attack complexity is classified as high. An attacker must rely on secondary information leaks to acquire a valid UUID. Common vectors for acquiring these IDs include log exposures, HTTP referrer headers, webhooks, or secondary information disclosure vulnerabilities.
Once a target UUID is acquired, the exploitation flow is straightforward. The attacker logs into the Bugsink instance and navigates to their own project's issue list. By executing a simple HTTP GET request with the unauthorized target UUID injected into their authorized issue view path, the attacker bypasses the isolation logic, reading raw crash data from the target project.
The impact of CVE-2026-47715 is restricted to unauthorized data disclosure within the boundaries of the self-hosted Bugsink database. An attacker cannot use this vulnerability to write, modify, or delete database entries, nor does the vulnerability support remote execution of arbitrary system commands.
However, the confidentiality impact is significant within multi-project setups. Crashes captured by error-tracking software frequently log sensitive runtime state. This state can include plaintext database connection strings, local execution variables, environment configurations, application source code paths, user session cookies, and authorization headers.
While the CVSS score is rated at 3.1 (Low) due to the high attack complexity of guessing high-entropy UUIDs, administrators must recognize that if a secondary leak exposes these identifiers, the protection offered by project isolation collapses. This makes the bug a high-priority concern for multi-tenant deployments.
The primary remediation path is upgrading the self-hosted Bugsink application to version 2.2.0 or higher. The release notes and download packages are available on the official GitHub repository at https://github.com/bugsink/bugsink/releases/tag/2.2.0.
Administrators can also implement temporary detection measures by analyzing web server access logs for anomalous traffic patterns. Specifically, look for multiple rapid requests containing matching issue path segments paired with rapidly changing event UUIDs in the URI path:
GET /issues/issue/45/event/7f18a221f4bd4618a8039d6e492f168d/details/
GET /issues/issue/45/event/9c33b1e32ad44bb19fcf42a78ef4210a/details/
Additionally, because Bugsink resolved a related cross-project sourcemap leakage in the same release, operators should execute the provided Django management command to remove unmapped or legacy diagnostic files. This ensures that historical assets uploaded without explicit project boundaries are purged from the host filesystem:
python manage.py delete_legacy_sourcemapsCVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Bugsink Bugsink | < 2.2.0 | 2.2.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 3.1 (Low) |
| EPSS Score | 0.00028 |
| Exploit Status | None / No Public Exploit Available |
| KEV Status | Not Listed |
The system fails to check if the user is authorized to access the resource specified by the user-controlled key.
TinyMCE versions 6.8.0 through 7.0.1 contain a high-severity Cross-Site Scripting (XSS) vulnerability. The flaw exists in the custom HTML parser and sanitizer module, which incorrectly manages SVG namespace scopes when parsing nested elements. A low-privileged or unauthenticated attacker can submit a crafted HTML payload containing nested SVG structures to bypass sanitization filters, leading to arbitrary JavaScript execution in the context of the victim's browser session.
CVE-2026-47759 is a critical stored Cross-Site Scripting (XSS) vulnerability affecting multiple active branches of the TinyMCE rich text editor. The flaw resides in the editor's handling of user-controlled, prefixed internal attributes, such as data-mce-href, data-mce-src, and data-mce-style. When processing raw HTML inputs, TinyMCE's internal validation schema neglects to inspect these custom prefixed attributes. During HTML serialization, the editor's engine extracts these unsanitized values and copies them back into standard executable attributes, overwriting any previously sanitized standard values and leading to execution of arbitrary code.
A high-severity stored Cross-Site Scripting (XSS) vulnerability was identified in the TinyMCE rich text editor. The flaw exists in the handling of the 'protect' configuration option, where forged placeholder comments containing malicious payloads bypass the editor's sanitization routines and execute arbitrary JavaScript during serialization and content restoration.
An authorization bypass and client-side property tampering vulnerability (CVE-2026-47742) in the Shopper headless admin panel (built on Laravel and Livewire) allows low-privileged users to modify arbitrary product records (Insecure Direct Object Reference). This occurs due to unlocked public model properties and a complete lack of access control checks on mutating sub-form store methods.
Shopper is an open-source headless e-commerce administration panel built on Laravel, Livewire, and Filament. Prior to version 2.8.0, the admin tables for PaymentMethods, Currencies, and Carriers exposed inline toggles and per-record actions that could be modified by any authenticated user without verifying the corresponding administrative permissions on the backend.
Bugsink prior to version 2.2.0 is vulnerable to Broken Object Level Authorization (BOLA). The issue list view authorizes access based on the project in the URL path but applies requested bulk actions to submitted issue UUIDs globally, without verifying project ownership.