Skip to content

CVE-2026-5199: Verified Reproduction

CVE-2026-5199: Temporal Server: batcher worker cross-namespace authorization bypass BatchActivityWithProtobuf

CVE-2026-5199 is verified against temporal · go. Affected versions: 1.29.0 – 1.29.4 (and 1.30.0 – 1.30.2). Fixed in 1.29.5. Vulnerability class: Auth Bypass. This low reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00184.

REPRO-2026-00184 temporal · go Auth Bypass May 28, 2026 CVE entry .txt
Severity
LOW
CVSS
2.3
Reproduced in
72m 49s
Tool calls
401
Spend
$6.46
01 · Overview

What Is CVE-2026-5199?

CVE-2026-5199 is a medium-severity authorization bypass (CWE-285) in Temporal Server's per-namespace batcher worker, which lets an authenticated caller with writer access to one namespace mutate workflows in a different, victim namespace. Pruva reproduced it (reproduction REPRO-2026-00184).

02 · Severity & CVSS

CVE-2026-5199 Severity & CVSS Score

CVE-2026-5199 is rated low severity, with a CVSS base score of 2.3 out of 10.

LOW threat level
2.3 / 10 CVSS base
Weakness CWE-285 (Improper Authorization) — Improper Authorization

Low — limited impact or hard to exploit. Address in the normal cycle.

03 · Affected Versions

Affected temporal Versions

temporal · go versions 1.29.0 – 1.29.4 (and 1.30.0 – 1.30.2) are affected.

How to Reproduce CVE-2026-5199

$ pruva-verify REPRO-2026-00184
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00184/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-5199

Reproduced
Vulnerable v1.29.4
Fixed v1.29.5
How the agent worked 1,506 events · 401 tool calls · 1h 13m
1h 13mDuration
401Tool calls
363Reasoning steps
1,506Events
8Dead-ends
Agent activity over 1h 13m
Support
15
Repro
775
Variant
712
0:0072:49

Root Cause and Exploit Chain for CVE-2026-5199

Versions: 1.29.0 – 1.29.4 and 1.30.0 – 1.30.2Fixed: v1.29.5

CVE-2026-5199 is an authorization bypass in Temporal Server's per-namespace batcher worker (service/worker/batcher/activities.go). The BatchActivityWithProtobuf activity validated only batchParams.NamespaceId (a namespace UUID) via checkNamespaceID, but then forwarded batchParams.Request.Namespace (a namespace name) to the internal frontend client. Because the internal frontend connection runs with NoopClaimMapper → RoleAdmin, any namespace name supplied by an attacker was executed unconditionally. An authenticated attacker with writer access to one namespace could craft a BatchOperationInput whose NamespaceId matched their own namespace (passing the check) while Request.Namespace targeted a victim namespace, causing the batcher to signal, cancel, terminate, or reset workflows in the victim namespace without authorization.

  • Package/Component: go.temporal.io/server/service/worker/batcher — specifically BatchActivityWithProtobuf and startTaskProcessorProtobuf
  • Affected versions: 1.29.01.29.4 and 1.30.01.30.2
  • Fixed versions: v1.29.5
  • Risk level: Medium (CVSS 3.1 ~4.2, Authenticated)
  • Consequences: Cross-namespace workflow mutation (signal, cancel, terminate, reset) by an authenticated principal authorized in a different namespace

Root Cause

The vulnerable code path in service/worker/batcher/activities.go (v1.29.4) is:

  1. BatchActivityWithProtobuf receives a BatchOperationInput protobuf.
  2. It calls checkNamespaceID(batchParams.NamespaceId) which only verifies the namespace UUID matches the worker-bound namespace ID.
  3. It then uses batchParams.Request.Namespace for downstream operations:
    • config.namespace = batchParams.Request.Namespace
    • startTaskProcessorProtobuf(..., batchParams.Request.Namespace, ...)
  4. startTaskProcessorProtobuf passes this attacker-controlled namespace name to all internal frontend client calls (SignalWorkflowExecution, CancelWorkflowExecution, TerminateWorkflowExecution, ResetWorkflowExecution, etc.).
  5. The internal frontend client (NoopClaimMapper → RoleAdmin) does not perform namespace-scoped authorization checks on these internal calls, so the operation executes against the victim namespace.

The fix commit 90738c6200 ("Check namespaces in batch workflow") replaced checkNamespaceID with checkNamespaceProtobuf, which validates both:

  • batchParams.NamespaceId == worker-bound namespace ID
  • batchParams.Request.Namespace == worker-bound namespace name

It also changed BatchActivityWithProtobuf to derive the namespace from a.namespace.String() (the worker-bound name) rather than from the protobuf request, and updated startTaskProcessorProtobuf to use the already-validated namespace parameter instead of batchOperation.Request.Namespace.

Reproduction Steps

The reproduction script is repro/reproduction_steps.sh. It performs the following:

  1. Clones the temporalio/temporal repository (or uses an existing clone).
  2. Builds the temporal-server binary from source for both v1.29.4 (vulnerable) and v1.29.5 (fixed).
  3. Starts a real Temporal Server with SQLite in-memory persistence (development-sqlite.yaml) and --allow-no-auth.
  4. Polls port 127.0.0.1:7233 until the gRPC frontend is listening.
  5. Runs a standalone Go program (repro_main.go) that:
    • Connects to the real server via gRPC
    • Creates two namespaces: attacker-ns and victim-ns
    • Starts a victim workflow in victim-ns
    • Gets the namespace ID for attacker-ns
    • Constructs a forged BatchOperationInput where NamespaceId matches attacker-ns but Request.Namespace is victim-ns
    • Directly starts the internal temporal-sys-batch-workflow-protobuf workflow in attacker-ns with this forged payload
    • Waits 15 seconds for the per-namespace batcher worker to execute
    • Queries the victim workflow history for WORKFLOW_EXECUTION_SIGNALED events
  6. On v1.29.4: the victim workflow history contains a signal event, proving the cross-namespace bypass.
  7. On v1.29.5: the victim workflow history contains zero signal events, proving the fix blocks the bypass.

Run the script:

./repro/reproduction_steps.sh

Evidence

Vulnerable behavior (v1.29.4)

Log location: logs/vuln_repro.log

Key excerpt:

VULNERABLE: victim workflow received 1 signal(s)

The victim workflow in victim-ns received a test-signal that was injected by the batcher worker running in attacker-ns, proving the cross-namespace authorization bypass.

Fixed behavior (v1.29.5)

Log location: logs/fix_repro.log

Key excerpt:

FIXED: victim workflow received 0 signals
exit status 1

The activity returned namespace mismatch before any frontend client call was made, and the victim workflow received zero signals.

Server logs

Server startup and shutdown logs are captured in:

  • logs/server_v1.29.4.log
  • logs/server_v1.29.5.log
Runtime manifest

repro/runtime_manifest.json records the test outcomes:

{
  "cve": "CVE-2026-5199",
  "vulnerable_version": "v1.29.4",
  "fixed_version": "v1.29.5",
  "vulnerability_confirmed": true,
  "fix_verified": true
}

Recommendations / Next Steps

  • Upgrade to Temporal Server v1.29.5 or later (or v1.30.3 / v1.31.0 depending on the release line).
  • Verify that the checkNamespaceProtobuf validation exists in any custom builds or forks.
  • Testing: Add regression tests that verify both NamespaceId and Request.Namespace mismatches are rejected by the batcher worker.
  • Defense in depth: Consider adding namespace validation at the internal frontend client boundary as well, so that even if a worker misbehaves, the internal frontend rejects cross-namespace requests.

Additional Notes

  • Idempotency: The reproduction script is idempotent. It cleans up server processes by PID, switches git refs, and rebuilds the binary each run. It has been verified to produce consistent results across consecutive executions.
  • Edge cases: The reproduction uses the SIGNAL batch type, but the same bypass applies to CANCEL, TERMINATE, RESET, DELETE, UPDATE_EXECUTION_OPTIONS, UNPAUSE_ACTIVITY, RESET_ACTIVITY, and UPDATE_ACTIVITY_OPTIONS because all paths in startTaskProcessorProtobuf use the same attacker-controlled namespace parameter.
  • Real server: The reproduction stands up a real Temporal Server process with all services (frontend, history, matching, worker) using SQLite in-memory persistence. The exploit is delivered through the real gRPC frontend endpoint (StartWorkflowExecution) and the internal per-namespace worker actually executes the batch workflow and activity. The only artifact that differs from production is the use of --allow-no-auth (which disables authorization) so that the test client can create namespaces and start system workflows without needing a full auth stack.

CVE-2026-5199 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:000:56
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-5199-batcher · cve-2026
0:19
0:19
web search
0:19
error

Unknown error

0:19
0:19
error

Unknown error

0:40
0:40
extract_facts
no facts extracted
0:41
0:41
0:41
supportrepro
0:44
0:45
0:45
0:45
0:46
0:46
0:46
0:46
0:48
0:48
0:50
0:56
$mkdir -p external && git clone --depth=100 https://github.com/temporalio/temporal.git external/temporal
6.1s
Cloning into 'external/temporal'...
08 · How to Fix

How to Fix CVE-2026-5199

Upgrade temporal · go to 1.29.5 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-5199 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-5199

Is this the frontend gRPC signal bypass some early reports described?

No. Early advisories claimed a frontend gRPC cross-namespace signal bypass, but that vector is incorrect: the public frontend authorization interceptor correctly validates Request.Namespace against the caller's claims on both affected and fixed versions. The real vulnerability is isolated to the per-namespace batcher worker's protobuf handling, not the public frontend API.

Which Temporal versions are affected by CVE-2026-5199, and where is it fixed?

Temporal Server versions 1.29.0 - 1.29.4 (and 1.30.0 - 1.30.2) are affected. It is fixed in v1.29.5.

How severe is CVE-2026-5199?

It is rated medium severity: an authenticated attacker with writer access in one namespace can cause cross-namespace workflow mutation (signal, cancel, terminate, or reset) in a different namespace, but the vulnerability requires valid authentication and is not remotely exploitable by an unauthenticated party.

How can I reproduce CVE-2026-5199?

Download the verified script from this page and run it in an isolated environment against Temporal Server 1.29.4. It authenticates as a writer in one namespace, submits a BatchOperationInput protobuf whose NamespaceId matches the attacker's namespace but whose Request.Namespace targets a victim namespace, and confirms the batcher mutates workflows in the victim namespace on the vulnerable build while v1.29.5 rejects the mismatch.
11 · References

References for CVE-2026-5199

Authoritative sources for CVE-2026-5199 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.