# OpenChoreo: Authorization bypass on WorkflowRun update allows cross-project takeover of workflow runs

OpenChoreo authorized WorkflowRun updates using ownership labels from the request body while mutating the run named in the URL, letting a low-privileged caller seize another project's run.

- Payout: Research
- Severity: high
- Program: OpenChoreo
- Found by: Tike00
- Disclosed: 2026-10-21
- CVE: CVE-2026-113727
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-46r4-q7wv-32fc
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-46r4-q7wv-32fc
- Tags: area:cloud domain:api domain:cloud impact:data-leak impact:integrity kind:research platform:ghsa sev:high tech:go tech:kubernetes technique:source-review vuln:access-control vuln:auth-bypass vuln:idor

**Target:** OpenChoreo API server, PUT /workflowruns/{runName} endpoint
**Root cause:** The workflowrun:update authorization check derived project/component ownership from the submitted object's openchoreo.dev/project and openchoreo.dev/component labels, while the mutated object was selected by the URL path; nothing bound the two together.
**Steps:**
1. Authenticate with a principal holding workflowrun:update at project or component scope in the victim's namespace (e.g. workload-publisher).
2. Learn the name of a WorkflowRun belonging to another project/component in the same namespace.
3. Send `PUT .../workflowruns/{victimRunName}` with a body carrying openchoreo.dev/project and openchoreo.dev/component labels for the component you legitimately control.
4. Authorization passes against the body labels; the stored victim run is rewritten with the attacker's ownership labels.
5. Subsequent view/logs/events/status/delete checks read the stored labels and now grant access to the hijacked run.
**How found:** Reporter noticed the authorization decision consumed ownership metadata from the request body while the object identity came from the URL path, and that nothing enforced agreement between them.
**Exploitation:** An authenticated CI-style token with workflowrun:update sends a PUT to the victim run's URL with attacker-owned labels in the body; the check passes and the run's ownership labels are overwritten, transferring authority so the attacker can read build logs (source paths, registry destinations, accidentally echoed credentials), read Kubernetes events, delete the run, and overwrite spec.workflow.parameters on pending runs.
**Escalation:** Label rewrite converts a single update permission into full read/delete control over any run in the namespace, since all other checks derive scope from stored labels; also enables wedging runs in ComponentValidationFailed or downgrading them to standalone runs skipping component validation.
**Insight:** When ownership is encoded in labels, check whether the authz layer reads those labels from the submitted object or the stored one — any endpoint that authorizes on body-supplied labels but mutates by URL key is a CWE-639 candidate, and the same mismatch often re-grants read/delete on follow-up calls.

