CVE-2026-81505
## 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 -- Conv
Properties
- ghsa_id
- GHSA-p5vg-v7mj-f6q4
- severity
- high
- summary
- Convoy: Cross-Tenant Source IDOR Leaks Plaintext Message Broker Credentials
- cve_id
- CVE-2026-81505
- signal_observed_at
- 2026-09-18T17:46:44+00:00
- is_ghsa_only
- false
- ghsa_published
- 2026-09-18T17:17:45Z
- source_url
- https://github.com/advisories/GHSA-p5vg-v7mj-f6q4
- ghsa_updated
- 2026-09-18T17:17:48Z
Related Entities (4)
VULNERABLE_TO (1)
AFFECTS (1)
HAS_WEAKNESS (1)
REPORTED_BY (1)
Explore deeper with Ninja Signal's threat intelligence graph