Sep 19, 2026·5 min read·7 visits
Convoy versions prior to 26.6.8 allow low-privilege authenticated users or project-scoped API keys to bypass tenant isolation boundaries and extract unredacted message broker credentials of other projects by querying specific Source IDs.
CVE-2026-81505 is a high-severity Broken Object Level Authorization (BOLA) / Insecure Direct Object Reference (IDOR) vulnerability in Convoy, a cloud-native webhooks gateway. In affected versions prior to 26.6.8, the single-item Source retrieval API endpoint authorizes project access but fails to confirm if the requested Source belongs to that specific project. This logical flaw allows authenticated users or project-scoped API key holders to bypass tenant isolation boundaries and retrieve unredacted, plaintext message broker credentials for Apache Kafka, Amazon SQS, RabbitMQ, and Google Cloud Pub/Sub belonging to other tenants. This issue is fully patched in version 26.6.8.
Convoy serves as a high-performance, cloud-native webhooks gateway designed to manage, dispatch, and monitor webhook events. In multi-tenant deployments, isolation between logical projects is maintained through unique identifiers, where users or API keys are scoped strictly to specific projects. The primary attack surface resides in the control-plane REST APIs exposed for resource configuration and inspection.\n\nThe vulnerability designated as CVE-2026-81505 represents a classic Broken Object Level Authorization (BOLA) or Insecure Direct Object Reference (IDOR) flaw within the /api/v1/projects/{projectID}/sources/{sourceID} endpoint. While the API gateway validates the requester's authority over the {projectID} specified in the URL path, the application fails to enforce that the requested {sourceID} belongs to that authorized project.\n\nAn authenticated attacker with access to at least one valid project can leverage this logic gap to query and retrieve any webhook Source across the entire system. Because webhook Sources hold highly sensitive connection details, exploiting this vulnerability leads directly to the exposure of unredacted credentials for backend message brokers. This vulnerability is restricted to the single-item retrieval endpoint; the bulk list endpoint remains properly scoped.
The root cause of CVE-2026-81505 is located in the logical separation between the API routing layer's authorization check and the database retrieval layer. When a request is made to the endpoint GET /api/v1/projects/{projectID}/sources/{sourceID}, the system routes the request through an authentication and authorization middleware that validates the caller's rights to {projectID}.\n\nOnce authorization is confirmed, the router handler (Handler.GetSource) calls the backend service layer via sources.Service.FindSourceByID(ctx, projectID, sourceID). The primary design failure is that the underlying database query against the convoy.sources table is executed using only the primary key id (corresponding to {sourceID}). The query completely ignores the project_id context passed from the API route.\n\nBecause the database retrieval was not constrained by the project ID, and the application service layer did not implement a post-query validation check to compare the retrieved record's project_id with the client's authorized {projectID}, the service blindly returned the record. This lack of validation violates tenant isolation boundaries.
The vulnerability was resolved in commit 1cc67cd16fb1f8890cc83a3998d3f92dceb7fd06 by introducing an explicit tenant validation check in the FindSourceByID function located within internal/sources/impl.go.\n\ngo\n// FindSourceByID retrieves a source by its ID, scoped to the given project.\nfunc (s *Service) FindSourceByID(ctx context.Context, projectID, id string) (*datastore.Source, error) {\n\trow, err := s.repo.FetchSourceByID(ctx, common.StringToPgText(id))\n\tif err != nil {\n\t\tif errors.Is(err, pgx.ErrNoRows) {\n\t\t\treturn nil, datastore.ErrSourceNotFound\n\t\t}\n\t\treturn nil, &ServiceError{ErrMsg: "error retrieving source", Err: err}\n\t}\n\n-\treturn rowToSource(row)\n+ source, err := rowToSource(row)\n+ if err != nil {\n+ \treturn nil, err\n+ }\n+\n+ // FetchSourceByID keys only on the source id, so enforce the project scope\n+ // here (the sibling FindSourceByName/DeleteSourceByID scope in SQL). Without\n+ // this, any authorized caller could read another project's source by id,\n+ // including its plaintext broker credentials. Treat a cross-project hit as\n+ // not found so ids stay non-enumerable.\n+ if source.ProjectID != projectID {\n+ \treturn nil, datastore.ErrSourceNotFound\n+ }\n+\n+ return source, nil\n}\n\n\nBy adding the conditional statement if source.ProjectID != projectID, the service ensures that even if a database row is successfully retrieved using only the source identifier, the application rejects the request and returns a datastore.ErrSourceNotFound error if the source is owned by a different project. This prevents information disclosure and prevents ID enumeration attacks.
To exploit CVE-2026-81505, an attacker must first obtain a valid, authenticated session or an API key scoped to a project under their control (e.g., Project_A). The attacker also needs to identify or guess the UUID of a target webhook Source (e.g., source_B_uuid) belonging to another tenant's project (Project_B).\n\nThe attack flow is represented in the diagram below:\n\nmermaid\ngraph LR\n Attacker["Attacker\n(Auth for Project A)"]\n Gateway["Convoy API Gateway\n(Verifies Project A Access)"]\n ServiceLayer["Service Layer\n(Fetches Source B by ID)"]\n Database[("PostgreSQL\n(sources Table)")]\n\n Attacker -->|"GET /projects/Project_A/sources/Source_B"| Gateway\n Gateway -->|"FindSourceByID(Project_A, Source_B)"| ServiceLayer\n ServiceLayer -->|"SELECT * WHERE id = Source_B"| Database\n Database -->|"Returns Source B Record"| ServiceLayer\n ServiceLayer -->|"Leaks Source B Plaintext Credentials"| Attacker\n\n\nThe attacker crafts a direct HTTP request to the target Convoy instance, substituting the victim's source UUID in the place of the source ID, while keeping the attacker's own authorized project ID in the path parameters:\n\nhttp\nGET /api/v1/projects/Project_A_ID/sources/Project_B_Source_UUID HTTP/1.1\nHost: convoy.target.internal\nAuthorization: Bearer <Attacker_Project_A_API_Key>\nAccept: application/json\n\n\nBecause the routing layer only verifies authorization for Project_A_ID, the request is processed. The database retrieves the configuration details for Project_B_Source_UUID, which is returned in full, exposing raw, unredacted credentials.
The impact of exploiting CVE-2026-81505 is severe confidentiality compromise. Webhook sources are typically integrated with enterprise message brokers and streaming platforms. Consequently, their configuration records contain highly sensitive authentication credentials.\n\nAn attacker successful in exploiting this vulnerability can retrieve plaintext connection parameters, including Apache Kafka SASL usernames and passwords, Amazon Simple Queue Service (SQS) AWS IAM access keys and secret keys, RabbitMQ / AMQP passwords and URI strings, or Google Cloud Pub/Sub service account keys.\n\nExfiltration of these credentials grants the attacker direct access to downstream enterprise data streams, allowing them to read proprietary business events, inject unauthorized messages, or disrupt critical message queues, extending the impact far beyond the Convoy gateway itself.
The primary and recommended remediation is to upgrade all Convoy gateway installations to version v26.6.8 or later. This version enforces strict application-level validation on the retrieved source records to ensure they match the authorized project scope.\n\nIf upgrading cannot be performed immediately, temporary mitigation strategies include restricting project-scoped API key generation, limiting network-level access to the Convoy control plane, and auditing active API keys.\n\nAdditionally, security teams should implement centralized logging to monitor cross-tenant HTTP requests targeting the project endpoints. If exploitation is suspected or verified, immediately revoke and rotate all credentials associated with integrated message brokers.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
convoy frain-dev | < 26.6.8 | 26.6.8 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 (Authorization Bypass Through User-Controlled Key) |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 7.1 (High) |
| EPSS Score | Not Registered |
| Impact | Confidentiality: High (Plaintext credentials leak) |
| Exploit Status | None (No public PoCs) |
| KEV Status | Not Listed |
The system fails to prevent a user from accessing a resource by altering the direct object reference without verifying authorization for the specific object.
CVE-2026-84992 is a Cross-Site Scripting (XSS) vulnerability affecting md-editor-v3 before version 6.5.4. It occurs because the fenced-code block language parser directly interpolates unescaped language metadata into unquoted HTML attributes inside the custom rendering callback. This bypasses the built-in XSSPlugin which runs during the parsing phase, before rendering.
CVE-2026-77339 is a critical security vulnerability in Process Compose before version 1.120.0. The Model Context Protocol (MCP) Server-Sent Events (SSE) listener transport subsystem fails to validate the HTTP Host and Origin headers, and does not enforce authentication. This omissions expose local loopback listeners to DNS rebinding attacks orchestrated by malicious remote websites visited by developers, enabling unauthorized process control and arbitrary command execution.
CVE-2026-77301 is a critical uncontrolled resource allocation vulnerability in the popular Node.js library adm-zip (versions prior to 0.6.1). During ZIP decompression of asynchronous entries, the library trusts the uncompressed size metadata declared in the central directory headers. Because Node.js's streaming zlib API completely ignores the maxOutputLength configuration, a crafted ZIP archive (decompression bomb) causes the application to continually allocate resident memory buffers on the heap without limits, causing rapid memory exhaustion and a process-level Out-of-Memory (OOM) crash.
This report details CVE-2026-91127 (GHSA-3753-m2x2-q623), a high-severity DOM Cross-Site Scripting (DOM XSS) vulnerability in the file-viewer workspace developed by flyfish-dev. The legacy Word document (.doc) parser fails to restrict hyperlink URI schemes when rendering extracted document targets into generated HTML. As a result, a remote attacker can construct a malicious legacy DOC file containing scripts inside hyperlink properties. When a user previews the file and clicks the hyperlink, arbitrary JavaScript executes in the context of the hosting origin, enabling session hijacking, credential theft, or unauthorized API interaction.
An authorization bypass and tenant isolation vulnerability in Perses prior to version 0.54.0-beta.3 allows authenticated viewers to access unauthorized project resources by manipulating query parameters or querying unmapped ephemeral endpoints.
CVE-2026-63199 is a critical missing authorization vulnerability (CWE-862) in Perses versions 0.43.0 to 0.54.0-rc.0. It allows low-privileged attackers to retrieve and exfiltrate highly sensitive credentials (secrets) from different scopes by configuring a malicious datasource pointing to an attacker-controlled endpoint.