CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-88978

CVE-2026-88978: Multi-Tenant Isolation Failure in Hatchet Durable Workflow Engine

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 23, 2026·7 min read·17 visits

Executive Summary (TL;DR)

Hatchet fails to restrict durable event log queries to the caller's tenant ID, allowing authenticated workers to view task metadata from other tenants if the target task UUID is known.

CVE-2026-88978 is a critical cross-tenant data exposure vulnerability in Hatchet, a platform for orchestrating background tasks and durable workflows. The flaw exists in the durable-task event retrieval system where client-supplied task, node, and branch UUIDs are resolved via the ListSatisfiedEntries database query without verifying the tenant ownership of the requesting worker context.

Vulnerability Overview

Hatchet is an open-source orchestration engine designed to manage background tasks, AI agents, and durable workflows. In multi-tenant environments, the control plane is responsible for enforcing strict isolation boundaries, ensuring that authenticated workers can only retrieve, execute, or query data belonging to their designated tenant context. Real-time scheduling and execution flow state is maintained through high-performance gRPC channels connecting workers to the central control plane engine.

A security audit of the event retrieval implementation identified a multi-tenant isolation bypass, designated as CVE-2026-88978. The vulnerability is located within the WorkerStatus gRPC pathway, which processes status check queries from active worker daemons. Due to a missing authorization filter, the system resolves client-supplied task, node, and branch UUIDs without validating that the requesting worker possesses legitimate access rights to the tenant containing those objects.

This security flaw corresponds to CWE-639 (Authorization Bypass Through User-Controlled Key) and CWE-863 (Incorrect Authorization). The underlying application validates the worker's session credentials but fails to enforce tenant-scoped access parameters during database queries. As a result, any authenticated tenant worker on a shared deployment can access event-log entries belonging to independent organizations, provided the target resource identifiers are known.

Root Cause Analysis

The technical root cause of CVE-2026-88978 resides inside the file pkg/repository/durable_events.go and its execution of the ListSatisfiedEntries SQL query. When an authenticated worker calls the WorkerStatus gRPC service, the control plane resolves the state of pending durable tasks. To retrieve status information, the repository layer queries the database via the GetSatisfiedDurableEvents function, passing in client-provided arrays of task external IDs, node IDs, and branch IDs.

Prior to the patch introduced in version 0.106.1, the underlying PostgreSQL query joined the v1_lookup_table and v1_task tables using only the client-supplied UUIDs as search keys. The query omitted any condition verifying that the tenant_id column of the target records matched the tenant_id associated with the requesting worker's authenticated session. Because the database engine executes join operations globally across shared relational tables, matching records across all tenants are returned to the caller.

While Hatchet generates durable task identifiers using high-entropy UUIDv4 values, which prevents practical brute-force guessing attacks, this design pattern introduces structural insecure direct object references (IDOR). If a target UUIDv4 is exposed through external logs, diagnostic consoles, or network transit interceptions, the isolation boundary between tenants is nullified. Relying on UUID unguessability as the sole protective control violates fundamental multi-tenant software architecture principles.

Code Diff and Patch Analysis

Remediation of this vulnerability required updating the database query definitions, re-generating the Go database drivers using sqlc, and modifying the calling conventions in the repository layer. The primary fix was implemented in the commit 15bc7923d3a8ebfeb0d88c19160dd24828921e85.

In the database schema definition file pkg/repository/sqlcv1/durable_event_log.sql, a strict WHERE clause was appended to restrict the join lookup to records matching the caller's tenant identifier:

-- Vulnerable Query Structure
WITH inputs AS (
    SELECT * FROM unnest(@taskExternalIds::UUID[]) as external_id
)
SELECT lt.id, lt.tenant_id, t.id as task_id
FROM inputs i
JOIN v1_lookup_table lt ON lt.external_id = i.external_id
JOIN v1_task t ON (t.id, t.inserted_at) = (lt.task_id, lt.inserted_at)
 
-- Patched Query Structure (v0.106.1)
WITH inputs AS (
    SELECT * FROM unnest(@taskExternalIds::UUID[]) as external_id
)
SELECT lt.id, lt.tenant_id, t.id as task_id
FROM inputs i
JOIN v1_lookup_table lt ON lt.external_id = i.external_id
JOIN v1_task t ON (t.id, t.inserted_at) = (lt.task_id, lt.inserted_at)
WHERE lt.tenant_id = @tenantId::UUID

In the Go repository layer, the durableEventsRepository was updated to accept the tenant identifier and bind it to the parameters struct passed to sqlc. The following diff highlights the code modification in pkg/repository/durable_events.go:

// Vulnerable Repository Call
func (r *durableEventsRepository) GetSatisfiedDurableEvents(ctx context.Context, taskExternalIds []uuid.UUID, nodeIds []int64, branchIds []int64) {
	r.queries.ListSatisfiedEntries(ctx, db, ListSatisfiedEntriesParams{
		Taskexternalids: taskExternalIds,
		Nodeids:         nodeIds,
		Branchids:       branchIds,
	})
}
 
// Patched Repository Call (v0.106.1)
func (r *durableEventsRepository) GetSatisfiedDurableEvents(ctx context.Context, tenantId uuid.UUID, taskExternalIds []uuid.UUID, nodeIds []int64, branchIds []int64) {
	r.queries.ListSatisfiedEntries(ctx, db, ListSatisfiedEntriesParams{
		Taskexternalids: taskExternalIds,
		Nodeids:         nodeIds,
		Branchids:       branchIds,
		Tenantid:        tenantId,
	})
}

This structural patch ensures complete resolution of the vulnerability. When the PostgreSQL engine processes the updated query, any rows that do not match the requested tenantId are filtered out prior to returning, ensuring that database read operations remain confined to the caller's security boundary.

Attack Methodology and Verification

To exploit this vulnerability, an attacker must satisfy several preconditions. First, the attacker must have valid, authenticated credentials for a worker operating under Tenant A. Second, the attacker must acquire the specific UUIDv4 task identifier of a target task running within Tenant B's environment.

Once the target identifier is obtained, the attacker establishes a gRPC connection to the control plane, authenticating as a worker for Tenant A. The attacker then constructs a crafted WorkerStatus request payload containing the target UUIDv4 task identifier. The control plane forwards these parameters directly to the database layer without tenant validation.

Because the vulnerable query lacks an lt.tenant_id constraint, the database returns matched execution records from the lookup table, regardless of which tenant owns them. The control plane subsequently packages this data and transmits it back to the attacker's client, resulting in unauthorized data disclosure.

The logic flow of this multi-tenant bypass is visualized in the following diagram:

Impact and Severity Assessment

The security impact of CVE-2026-88978 is limited to a loss of confidentiality in multi-tenant deployments. Exploitation allows an attacker to inspect step event logs, parameters, and structural execution maps of workflows running in separate tenant spaces. In workflows coordinating AI agents or database synchronizations, these event logs may contain sensitive credentials, runtime variables, or proprietary data assets.

The vulnerability does not affect system availability or data integrity. The vulnerable query path is strictly read-only, preventing attackers from injecting tasks, modifying workflow states, or deleting records belonging to other tenants. No remote code execution vectors are directly exposed through this specific database query flaw.

CVSS v3.1 evaluated this issue at 4.3 (Medium Severity), reflecting the low complexity of the exploit offset by the necessity of obtaining a high-entropy UUIDv4 and possessing authenticated worker access. For single-tenant deployments of Hatchet, the risk profile is non-existent as all database records reside within a single administrative and security boundary.

Remediation and Detection

The recommended remediation path is to upgrade the Hatchet control plane and workers to version 0.106.1 or newer. This update applies the database schema modifications and ensures that all event querying is bound to verified tenant contexts. Administrators should review their active deployment tags and verify successful schema migration execution.

For systems where immediate patching is not feasible, log-level mitigations should be applied. Configure workers and API gateways to suppress high-verbosity debugging outputs that might expose task, node, or branch UUIDv4 identifiers. Additionally, implementing network-level access control limits the exposure of the gRPC interface to verified worker subnets.

Detecting historical exploitation attempts requires auditing the database queries against the PostgreSQL engine. Security teams can execute queries to identify instances where the requesting worker's tenant registration differed from the tenant owner of the queried task uuid. Discrepancies in query telemetry indicate potential cross-tenant isolation violations.

Official Patches

hatchet-devFix Commit

Technical Appendix

CVSS Score
4.3/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
EPSS Probability
0.17%
Top 93% most exploited

Affected Systems

Hatchet Control PlaneHatchet Durable Event Logging System
AttributeDetail
CWE IDCWE-639 / CWE-863
Attack VectorNetwork (gRPC)
CVSS Score4.3 (Medium)
Exploit StatusNone (No public exploit available)
KEV StatusNot Listed
ImpactCross-tenant data exposure
CWE-639
Authorization Bypass Through User-Controlled Key

The system uses user-controlled keys to access database records directly without verifying that the requesting user is authorized to view those records.

Vulnerability Timeline

Vulnerability patch merged into the main branch
2026-09-04
GitHub Security Advisory GHSA-992g-9cr3-vm5x published
2026-09-21
CVE-2026-88978 published to the CVE database
2026-09-21

References & Sources

  • [1]GitHub Security Advisory GHSA-992g-9cr3-vm5x
  • [2]Fix Commit 15bc792
  • [3]CVE-2026-88978 Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•less than a minute ago•GHSA-VGHH-5RFX-XHQ8
9.9

CVE-2026-48749: Arbitrary Host File Read and Write via Malicious Image Symlink in Canonical LXD and Incus

CVE-2026-48749 (tracked as GHSA-vghh-5rfx-xhq8 for LXD and GHSA-2q3f-q5pq-g8wv for Incus) is a critical container escape vulnerability in the Canonical LXD and Linux Containers Incus system container managers. By importing a specially crafted container image archive containing duplicate tar member headers, an authenticated attacker can replace the instance rootfs directory with a symbolic link pointing to the underlying host root filesystem. When performing file operations on a stopped container, the privileged forkfile helper binary resolves the symbolic link without confinement and chroots directly into the host filesystem, granting arbitrary root-level file read and write access.

Amit Schendel
Amit Schendel
0 views•9 min read
•about 1 hour ago•GHSA-FMC8-P6Q7-75CC
9.9

GHSA-fmc8-p6q7-75cc: Argument Injection in Canonical LXD Backup Compression Leads to Host Root Code Execution

GHSA-fmc8-p6q7-75cc (associated with CVE-2026-48755) is a critical argument injection vulnerability in Canonical LXD (github.com/canonical/lxd). The vulnerability occurs during instance and storage volume backup operations when processing the user-supplied compression_algorithm configuration parameter. While LXD validates the primary executable token against an allowlist of supported compression binaries, it fails to sanitize or restrict subsequent tokens parsed via shellquote.Split. These additional arguments are passed directly to exec.Command. An authenticated attacker with privileges to trigger backups can inject command-line flags for utilities like zstd to read staged files from a container filesystem and write them to arbitrary paths on the underlying host filesystem, such as /etc/cron.d/, achieving root-level arbitrary code execution on the host.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 2 hours ago•GHSA-PJFF-C2WC-F6JM
9.9

CVE-2026-48769: Arbitrary File Write and Remote Code Execution via Trusted Image Hash in Canonical LXD and Linux Containers Incus

A critical path traversal vulnerability caused by improper input validation (CWE-20) exists in the direct image download handler of Canonical LXD and Linux Containers Incus. When an authenticated user requests an image import using the URL source type, the daemon reads the image fingerprint from an untrusted HTTP response header (`Incus-Image-Hash` or `LXD-Image-Hash`) without validating that it conforms to a SHA-256 format. This unvalidated string is concatenated directly into a filesystem path via `filepath.Join` prior to file creation and cryptographic verification, allowing directory traversal sequences to write arbitrary files on the host filesystem as root.

Alon Barad
Alon Barad
7 views•10 min read
•about 6 hours ago•CVE-2026-9639
6.5

CVE-2026-9639: Authenticated Denial of Service via Nil-Pointer Dereference in Canonical LXD Custom Volume Backup Import

CVE-2026-9639 (GHSA-j93m-3j9p-m5m8) is a null pointer dereference vulnerability in Canonical LXD affecting versions 5.0.0 through 5.21.4 and 6.0 through 6.8. The flaw resides in the (*lxdBackend).CreateCustomVolumeFromBackup method within lxd/storage/backend_lxd.go. An authenticated attacker with the can_create_storage_volumes permission can upload a crafted custom volume backup tarball that omits the expires_at field on a snapshot entry, triggering an unhandled SIGSEGV panic and terminating the LXD daemon.

Amit Schendel
Amit Schendel
6 views•9 min read
•about 7 hours ago•CVE-2026-33050
8.8

CVE-2026-33050: OS Command Injection in GeoNode Vector Upload Handler

An operating system command injection vulnerability (CWE-78) exists in GeoNode versions prior to 5.1.0. The vulnerability occurs in the vector upload processing pipeline when handling user-supplied geospatial files. By supplying a crafted layer name containing shell metacharacters, an authenticated attacker with basic data upload privileges can execute arbitrary commands on the underlying server or container hosting the GeoNode application and Celery worker processes.

Alon Barad
Alon Barad
6 views•9 min read
•about 8 hours ago•CVE-2026-46429
5.5

CVE-2026-46429: Unrestricted File Upload and Validation Bypass in GeoNode

GeoNode versions prior to 5.0.3 contain an unrestricted file upload vulnerability (CWE-434) within the document and dataset ingestion architecture. Authenticated low-privileged users can bypass upload validation via direct REST API interactions, file extension masquerading, metadata mutation via PATCH requests, or malicious archive submissions. This allows attackers to store and serve dangerous file types, alter on-disk file references, or trigger path traversal and resource exhaustion during archive extraction.

Amit Schendel
Amit Schendel
7 views•10 min read