{
  "ticket_id": "CVE-2026-5199-BATCHER",
  "code_root": "external/temporal",
  "source": {
    "type": "cve",
    "cve_id": "CVE-2026-5199",
    "ghsa_id": null,
    "repo": "https://github.com/temporalio/temporal"
  },
  "facts": {
    "issue_summary": "Temporal Server's batcher worker BatchActivityWithProtobuf in service/worker/batcher/activities.go validates batchParams.NamespaceId via checkNamespaceID but does NOT validate batchParams.Request.Namespace before forwarding the request to the internal frontend client. Because the internal frontend runs with NoopClaimMapper -> RoleAdmin, the forged namespace name is executed unconditionally. An attacker with a valid auth token for namespace A can send a BatchActivity request whose protobuf payload's Request.Namespace names a different namespace B, causing the activity to signal/cancel/terminate/reset workflows in namespace B.",
    "vulnerability_type": "Authorization bypass in batcher worker protobuf batch path",
    "suspected_cwe": ["CWE-285"],
    "affected_versions": "1.29.0 through 1.29.4 (and 1.30.0 through 1.30.2)",
    "fixed_versions": ["v1.29.5"],
    "reproduce_version": "v1.29.4",
    "verify_fixed_version": "v1.29.5",
    "repo_url": "https://github.com/temporalio/temporal.git",
    "checkout_ref": "v1.29.4",
    "code_root": "external/temporal",
    "attacker_access": "Authenticated Temporal user with writer role in at least one namespace on the cluster. Attacker sends a batch operation via BatchActivityWithProtobuf with NamespaceId matching their own namespace but Request.Namespace set to a victim namespace name. No direct internal-frontend access is required.",
    "primary_entry_point": "service/worker/batcher/activities.go:BatchActivityWithProtobuf — the checkNamespaceID validation (v1.29.4) and subsequent startTaskProcessorProtobuf call that passes batchParams.Request.Namespace to the frontend client.",
    "build_hint": "go test -v -run 'TestBatch' ./service/worker/batcher/ (requires a minimal test harness that instantiates batchActivities with a mock FrontendClient and namespace metadata, then invokes BatchActivityWithProtobuf with a mismatched Request.Namespace)",
    "trigger_hint": "Construct a BatchOperationInput protobuf where NamespaceId equals the worker-bound namespace ID but Request.Namespace is set to a different victim namespace string. Pass it to BatchActivityWithProtobuf. On v1.29.4 checkNamespaceID returns nil, allowing the mismatched namespace to reach the frontend client. On v1.29.5 checkNamespaceProtobuf returns an error, blocking the call.",
    "end_to_end_requirement": "The reproduction MUST exercise the batcher worker code path (BatchActivityWithProtobuf), NOT the public frontend gRPC. A Go integration test in service/worker/batcher/ is acceptable. Verdict must show: (a) v1.29.4 allows the mismatched Request.Namespace to proceed through the activity, (b) v1.29.5 rejects it at checkNamespaceProtobuf, and (c) the legacy BatchActivity path is not the trigger (it already uses checkNamespace).",
    "tested_under": "Go test in service/worker/batcher against temporal v1.29.4 vs v1.29.5, using mock FrontendClient and handcrafted BatchOperationInput protobuf."
  }
}
