Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 274/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 08:00 UTC Customize Public modeDiscuss ChangeIntel on Discord

Convoy: Cross-Tenant Source IDOR Leaks Plaintext Message Broker Credentials

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-81505

Published

Convoy is a cloud native webhooks gateway. Prior to 26.6.8, Convoy's GET /api/v1/projects/{projectID}/sources/{sourceID} endpoint authorizes access to the project in the URL, but Handler.GetSource calls sources.Service.FindSourceByID() and fetches the Source only by sourceID without confirming that its ProjectID matches the authorized project. An authenticated user or project-scoped API key holder can substitute another tenant's Source identifier and receive that Source's complete record, including unredacted AMQP, Kafka, SQS, or Google PubSub credentials. The list endpoint remains project-scoped; the single-item Source lookup is affected. This issue is fixed in version 26.6.8.

Source published
18 Sep 2026 16:21:17 UTC
Source modified
18 Sep 2026 17:15:48 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 7.1 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

euvd · EUVD-2026-83051

Published

Convoy is a cloud native webhooks gateway. Prior to 26.6.8, Convoy's GET /api/v1/projects/{projectID}/sources/{sourceID} endpoint authorizes access to the project in the URL, but Handler.GetSource calls sources.Service.FindSourceByID() and fetches the Source only by sourceID without confirming that its ProjectID matches the authorized project. An authenticated user or project-scoped API key holder can substitute another tenant's Source identifier and receive that Source's complete record, including unredacted AMQP, Kafka, SQS, or Google PubSub credentials. The list endpoint remains project-scoped; the single-item Source lookup is affected. This issue is fixed in version 26.6.8.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Sep 18, 2026, 4:21:17 PM

dateUpdated: Sep 18, 2026, 5:15:48 PM

Source published
Sep 18, 2026, 4:21:17 PM (timezone not stated)
Source modified
Sep 18, 2026, 5:15:48 PM (timezone not stated)
Observed here
11 Nov 2026 16:10:16 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 7.1 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

nvd · CVE-2026-81505

Published

Convoy is a cloud native webhooks gateway. Prior to 26.6.8, Convoy's GET /api/v1/projects/{projectID}/sources/{sourceID} endpoint authorizes access to the project in the URL, but Handler.GetSource calls sources.Service.FindSourceByID() and fetches the Source only by sourceID without confirming that its ProjectID matches the authorized project. An authenticated user or project-scoped API key holder can substitute another tenant's Source identifier and receive that Source's complete record, including unredacted AMQP, Kafka, SQS, or Google PubSub credentials. The list endpoint remains project-scoped; the single-item Source lookup is affected. This issue is fixed in version 26.6.8.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Deferred

Weakness classifications: CWE-639

Original publisher date fields

published: 2026-09-18T17:17:02.103

lastModified: 2026-09-24T21:25:27.050

Source published
18 Sep 2026 17:17:02 UTC
Source modified
24 Sep 2026 21:25:27 UTC
Observed here
25 Oct 2026 16:19:10 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 7.1 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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

osv · GHSA-p5vg-v7mj-f6q4

Published

## Summary frain-dev/convoy (all versions up to and including v26.6.2, no patch available) lets any authenticated caller who is authorized on at least one project read ANY OTHER project's "Source" record by ID via GET /api/v1/projects/{projectID}/sources/{sourceID} -- regardless of whether that Source actually belongs to the project named in the URL. The response includes the Source's full PubSub broker configuration in plaintext (AMQP/Kafka/SQS/Google credentials), with no redaction. ## Details `Handler.GetSource` (api/handlers/source.go) resolves the caller's authorization against the {projectID} in the URL via retrieveProject(), then calls `sources.Service.FindSourceByID(ctx, project.UID, sourceID)` (internal/sources/impl.go). That function accepts a projectID parameter but never uses it: func (s *Service) FindSourceByID(ctx context.Context, projectID, id string) (*datastore.Source, error) { row, err := s.repo.FetchSourceByID(ctx, common.StringToPgText(id)) ... } The underlying SQL query (internal/sources/repo/queries.sql, `fetchSourceByID`) has no project_id predicate at all: SELECT ... FROM convoy.sources AS s LEFT JOIN convoy.source_verifiers sv ON s.source_verifier_id = sv.id WHERE s.id = $1 AND s.deleted_at IS NULL So the {projectID} in the URL only gates "is the caller authorized to view *a* project" -- it never re-validates that the fetched Source actually belongs to that project. `LoadSourcesPaged` (the list endpoint) does correctly scope by project; only the single-item GetSource lookup is affected. `SourceResponse{*datastore.Source}` embeds the full database record with no redaction, so if the leaked Source is an AMQP/Kafka type, its `pub_sub.*.auth.password` field (a live, plaintext broker credential) is returned verbatim. ## Proof of Concept 1. As a test account, create "Victim Project" and an AMQP Source in it with a known broker password (verified against a real RabbitMQ broker, not just stored -- Convoy performs a live connectivity check before persisting an AMQP source). 2. As the same or a different authenticated caller, create a completely separate "Attacker Project". 3. Call GET /api/v1/projects/{attacker_project_id}/sources/{victim_source_id} -- i.e. a request whose URL and authorization check only ever resolve the Attacker project. 4. Verified in a Docker lab (convoy v26.6.2): the request returns 200 with the Victim project's full Source object, including pub_sub.amqp.auth.password matching the secret set in step 1 exactly. The response's own `project_id` field is the Victim project's id, never the Attacker project id used in the URL/authorization check. 5. Negative control: an otherwise-identical request for a made-up source id under the same Attacker project returns 404, confirming this is a real, ID-specific hit and not a blanket-200 endpoint. (Community Edition license-gates org_limit=1/user_limit=1, so this PoC used one account with two projects rather than two separate companies -- the vulnerable query performs no project-ownership check regardless of license tier, so a licensed multi-org deployment has the identical exposure between genuinely different tenants.) <img width="1100" height="830" alt="1_live_poc_evidence" src="https://github.com/user-attachments/assets/b2d18d3f-8e70-40ec-ad7f-7f0ac1fdebe0" /> ## Impact Any authenticated user or project-scoped API key holder who has legitimate access to at least one project on a Convoy instance can read any other project's Source configuration by ID, including plaintext third-party message-broker credentials (AMQP/Kafka/SQS/Google PubSub). In a multi-tenant deployment this is a direct cross-customer credential leak. ## Fix Add a project_id predicate to the fetchSourceByID query (and audit other single-item repository lookups reachable via a {projectID} route for the same pattern), or re-check `source.ProjectID == project.UID` in the handler before returning the record. ## Affected / Patched Affected: <= v26.6.2 (latest release at time of report). No patched version available.

Source published
18 Sep 2026 17:17:45 UTC
Source modified
28 Sep 2026 17:10:51 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V4 · 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

Publisher rating · HIGH

osv · GO-2026-6523

Published

Convoy: Cross-Tenant Source IDOR Leaks Plaintext Message Broker Credentials in github.com/frain-dev/convoy

Source published
28 Sep 2026 16:43:40 UTC
Source modified
28 Sep 2026 17:00:17 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
OSV · upstream source license applies

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 12 Nov 08:00 UTC · 274 of 275 readable · 272 fully read · documentation 469/469 current