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

Convoy's GetSource endpoint ignores the URL projectID, letting any authenticated user read another project's Source and its plaintext broker credentials.

- Payout: Research
- Severity: high
- Program: Convoy
- Found by: GrayOM
- Disclosed: 2026-09-18
- CVE: CVE-2026-81505
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-p5vg-v7mj-f6q4
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-p5vg-v7mj-f6q4
- Tags: area:web domain:api impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:go technique:source-review vuln:access-control vuln:idor vuln:info-disclosure vuln:secrets-leak

**Target:** GET /api/v1/projects/{projectID}/sources/{sourceID} API endpoint
**Root cause:** FindSourceByID accepts a projectID parameter but never uses it, and the fetchSourceByID SQL query has no project_id predicate, so authorization only checks the caller can view some project, not that the Source belongs to it.
**Steps:**
1. Create a Victim Project with an AMQP Source holding a known broker password (Convoy live-checks connectivity before persisting).
2. Create a separate Attacker Project under the same authenticated caller.
3. Send `GET /api/v1/projects/{attacker_project_id}/sources/{victim_source_id}`.
4. Observe 200 with the Victim Source object, including `pub_sub.amqp.auth.password` matching the secret, and `project_id` equal to the Victim project.
5. Negative control: same request with a made-up source id returns 404.
**How found:** Code review of Handler.GetSource and sources.Service.FindSourceByID revealed the projectID parameter was accepted but unused, and the underlying SQL lacked a project_id predicate; confirmed with a Docker lab PoC and a 404 negative control.
**Exploitation:** Any authenticated user or project-scoped API key with access to at least one project enumerates Source IDs and requests them under their own projectID, harvesting plaintext AMQP/Kafka/SQS/Google PubSub credentials from other tenants.
**Escalation:** Leaked broker credentials grant direct access to third-party message brokers, enabling message interception/injection beyond Convoy itself.
**Insight:** When a service method takes a projectID/tenantID argument, grep for its actual use inside the function and the SQL — a parameter that is threaded through but never referenced in the WHERE clause is a reliable IDOR signal, especially on single-item lookups while list endpoints scope correctly.

