Skip to content
Heist/ feed
HighFix available

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

Type: advisorySource: OSV1 source record

## 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 singl

Announced Source revision 1
Original source ↗

GHSA-p5vg-v7mj-f6q4

Primary source · Revision 1

Imported from structured advisory data. Source references identify upstream records or fields; verify affected versions and your deployed configuration.

Security context

Source reference: osv:GHSA-p5vg-v7mj-f6q4

github.com/frain-dev/convoy

Source reference: /affected/0/package/name

Affected versions
Not stated in this record
Fixed versions
0.9.3-0.20260724092134-1cc67cd16fb1

Source reference: /affected/0/ranges

Prerequisites
Not stated in this record

Structured affected-version data

Original package identities and version rules from this source.

[
  {
    "ranges": [
      {
        "type": "SEMVER",
        "events": [
          {
            "introduced": "0"
          },
          {
            "fixed": "0.9.3-0.20260724092134-1cc67cd16fb1"
          }
        ]
      }
    ],
    "package": {
      "name": "github.com/frain-dev/convoy",
      "purl": "pkg:golang/github.com/frain-dev/convoy",
      "ecosystem": "Go"
    },
    "database_specific": {
      "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-p5vg-v7mj-f6q4/GHSA-p5vg-v7mj-f6q4.json"
    }
  }
]
Related CVEs
CVE-2026-81505

Source reference: /aliases

Publisher severity

high

Source reference: /database_specific/severity

Event
#23400 · Revision 1
Added to Heist Feed
Publisher date
Read the original announcement