GitHub Security Advisory: GHSA-55gc-6fmc-fpx9
Package: github.com/hatchet-dev/hatchet (GO)
Severity: MODERATE (CVSS 5.3)
CWE: CWE-639: Authorization Bypass Through User-Controlled Key, CWE-863: Incorrect Authorization
Vulnerable versions: <= 0.83.38
Patched in: 0.83.39

Summary: Hatchet affected by cross-tenant information disclosure in `listTasksByDAGIds`

Details:
## Summary

A missing authorization directive on the `GET /api/v1/stable/dags/tasks` endpoint caused Hatchet's tenant-membership check to be skipped for this route. A user authenticated to any tenant on the same Hatchet instance could query the endpoint with another tenant's UUID and a DAG UUID belonging to that tenant, and receive task metadata for that DAG.

This issue has been patched in **v0.83.39**. Hatchet Cloud has been patched and requires no action from users. Self-hosted users should upgrade.

## Impact

**Who is affected.** Multi-tenant Hatchet instances reachable by an attacker who can obtain an account on that instance. On Hatchet Cloud, account creation is open by default. On self-hosted instances, the API must be reachable by the attacker and the hostname known; instances deployed inside a VPC or with signup restricted are not exposed to arbitrary external actors.

**Prerequisites for exploitation.** An attacker needed:

1. An account on the target Hatchet instance.
2. The victim tenant's UUID.
3. At least one DAG UUID (`external_id`) belonging to that tenant.

The two UUIDs are not treated as secrets — they appear in URLs, API responses, audit logs, invitation flows, shared run links, and dashboard screenshots — but an attacker does need to learn them through some out-of-band channel before exploitation is possible.

**What could be disclosed.** For each child task of a targeted DAG, the endpoint returned:

- `display_name`, `action_id`, `step_id`
- `workflow_id`, `workflow_version_id`, `workflow_run_id`, `task_external_id`
- `tenant_id`, `retry_count`, `status`, timestamps
- `additional_metadata` (JSON)

The `additional_metadata` field is the most sensitive: Hatchet workflows commonly use it to carry domain context such as user identifiers, customer IDs, feature flags, or correlation tokens. Its contents vary by deployment.

**What was not disclosed.** The raw task `input` payload is not part of this endpoint's response shape and was not exposed through this issue. The scope is limited to task metadata, not task arguments or results.

**Exploitation status.** We have no evidence that this vulnerability was exploited prior to the patch.

## Root cause

Hatchet's multi-tenant authorization relies on an OpenAPI-driven middleware pipeline. Each authenticated operation declares `x-resources: ["tenant", ...]` in its spec. The `populator` middleware reads the declared resources, looks up the corresponding entities from request parameters, and stores them on the request context. The `authz` middleware then verifies that the authenticated user is a member of the tenant found on the context.

The `listTasksByDAGIds` operation accepted a `tenant` UUID as a query parameter, but its OpenAPI definition did not declare `x-resources: ["tenant"]`. As a result:

1. The populator, which early-returns when no resources are declared, did not populate the tenant onto the request context.
2. The authz middleware, which runs its membership check only wh