Skip to main content
Vulnerability Database/CVE-2026-81505

CVE-2026-81505: Convoy Information Disclosure Vulnerability

CVE-2026-81505 is an information disclosure flaw in Convoy webhooks gateway that allows authenticated users to access other tenants' source credentials. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-81505 Overview

Convoy, a cloud-native webhooks gateway maintained by frain-dev, contains a broken access control flaw in its Source lookup endpoint. Prior to version 26.6.8, the GET /api/v1/projects/{projectID}/sources/{sourceID} endpoint authorizes the request against the project in the URL but fetches the Source record using only the sourceID. An authenticated user or project-scoped API key holder can substitute another tenant's Source identifier and retrieve that Source's full record. The response includes unredacted AMQP, Kafka, SQS, or Google PubSub credentials. This issue is tracked as [CWE-639: Authorization Bypass Through User-Controlled Key].

Critical Impact

Any authenticated tenant can enumerate Source IDs across projects and exfiltrate plaintext message-broker credentials belonging to other tenants.

Affected Products

  • frain-dev Convoy versions prior to 26.6.8
  • Convoy control-plane deployments exposing the Sources API to multi-tenant users or project-scoped API keys
  • Self-hosted and managed Convoy instances integrating AMQP, Kafka, SQS, or Google PubSub sources

Discovery Timeline

  • 2026-09-18 - CVE-2026-81505 published to NVD
  • 2026-09-24 - Last updated in NVD database

Technical Details for CVE-2026-81505

Vulnerability Analysis

Convoy exposes a project-scoped REST API for managing webhook Sources. The handler Handler.GetSource accepts a projectID and sourceID from the URL path and validates that the caller has access to the specified project. It then delegates the lookup to sources.Service.FindSourceByID(), which queries the datastore using only the sourceID.

Because the service layer never re-checks that the returned Source's ProjectID matches the authorized project, the authorization decision applies to a project the caller already owns while the data returned belongs to a different project. The list endpoint remains correctly project-scoped, so the flaw is limited to the single-item Source lookup path.

Exploitation returns the complete Source record with its message-broker credentials unredacted, exposing AMQP, Kafka, Amazon SQS, and Google Cloud Pub/Sub secrets that downstream consumers use to authenticate to backing infrastructure.

Root Cause

The root cause is a missing tenant-scoping check in the data-access path. FindSourceByID accepted a projectID argument but did not use it when constructing the query, resulting in an Insecure Direct Object Reference (IDOR) whenever the identifier is guessed, leaked, or enumerated.

Attack Vector

An attacker authenticates as any low-privileged user or presents a valid project-scoped API key. The attacker then issues a GET against /api/v1/projects/{their-projectID}/sources/{victim-sourceID}. The server authorizes the request against the attacker's project but returns the victim's Source, including plaintext broker credentials that can be reused against the victim's messaging infrastructure.

go
// Patch: internal/sources/impl.go
// Before: FindSourceByID retrieves a source by its ID
// After:  FindSourceByID retrieves a source by its ID, scoped to the given project.
func (s *Service) FindSourceByID(ctx context.Context, projectID, id string) (*datastore.Source, error) {
    row, err := s.repo.FetchSourceByID(ctx, common.StringToPgText(id))
    if err != nil {
        // ...
    }
}
// Source: https://github.com/frain-dev/convoy/commit/1cc67cd16fb1f8890cc83a3998d3f92dceb7fd06

The accompanying commit also adds strings import handling in auth/realm/jwt/jwt.go to canonicalize JWT blacklist entries. See the GitHub commit 1cc67cd and the Convoy pull request #2755 for the complete patch.

Detection Methods for CVE-2026-81505

Indicators of Compromise

  • HTTP GET requests to /api/v1/projects/{projectID}/sources/{sourceID} where the returned Source's project_id differs from the URL projectID.
  • Bursts of sequential or randomized sourceID values from a single API key against the Sources endpoint.
  • Outbound authentication attempts to tenant AMQP, Kafka, SQS, or Google PubSub endpoints originating from unexpected source networks.

Detection Strategies

  • Enable access logging on the Convoy control plane and alert when a single principal queries Source identifiers spanning multiple projects.
  • Correlate application logs with database query logs to identify FetchSourceByID calls whose result set belongs to a project the caller does not own.
  • Review authentication logs for the AMQP, Kafka, SQS, and Google PubSub backends for logins from unfamiliar IP ranges shortly after Convoy API activity.

Monitoring Recommendations

  • Rate-limit and baseline per-API-key access to /sources/{sourceID} and flag deviations above the baseline.
  • Ingest Convoy audit logs into a centralized SIEM and build correlation rules that join API access with broker authentication events.
  • Track secret usage on issued broker credentials and alert on first-time-seen source IPs.

How to Mitigate CVE-2026-81505

Immediate Actions Required

  • Upgrade Convoy to version 26.6.8 or later, available in the Convoy v26.6.8 release notes.
  • Rotate all AMQP, Kafka, Amazon SQS, and Google Cloud Pub/Sub credentials configured as Convoy Sources that existed before the upgrade.
  • Audit Convoy access logs for cross-tenant GET /sources/{sourceID} responses and revoke any project-scoped API keys that show enumeration behavior.

Patch Information

The fix landed in Convoy 26.6.8. Service.FindSourceByID now scopes the datastore lookup by projectID, ensuring that a Source is returned only when its ProjectID matches the authorized project. Full details are published in GHSA-p5vg-v7mj-f6q4.

Workarounds

  • Restrict the Convoy control-plane API to trusted operator networks until the upgrade completes.
  • Revoke or narrow project-scoped API keys for tenants that do not require Source management.
  • Place a reverse proxy or API gateway in front of Convoy that validates the projectID path parameter against the caller's tenancy claim before the request reaches the handler.
bash
# Verify running Convoy version and upgrade
convoy version
# Pull the fixed release
docker pull ghcr.io/frain-dev/convoy:v26.6.8
# Restart the control-plane service after updating the image tag
docker compose up -d convoy

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.