CVE-2026-54136: Windmill Remote Code Execution Vulnerability
MODERATECVE-2026-54136 is a MODERATE remote code execution vulnerability (CWE-863: Incorrect Authorization) affecting Windmill libraries in the crates.io ecosystem. The issue involves resource-scoped api tokens can read script contents outside their allowed path via scripts/list_search. Remediation is available by upgrading affected packages to version 1.715.0.
CVE-2026-54136 at a Glance
How to Fix CVE-2026-54136
To remediate this vulnerability, upgrade all affected Windmill dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade windmill-api to 1.715.0
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for windmill-api
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-54136, inspect your project dependencies for Windmill:
inspect dependencies for windmill-api
Analyze the terminal output to locate any version of Windmill in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.715.0), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-863: Incorrect Authorization, where the product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check. In Windmill, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-54136 Affected Windmill Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
windmill-api
|
crates.io |
< 1.715.0
|
1.715.0
|
References
Frequently Asked Questions
What is CVE-2026-54136?
Which Windmill versions are affected?
What version fixes CVE-2026-54136?
Is windmill-api affected?
What CWE is associated with CVE-2026-54136?
How can I check crates.io dependencies for CVE-2026-54136?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-2ppx-66jv-wpw5",
"modified" : "2026-07-10T19:28:06Z",
"published" : "2026-07-10T19:28:06Z",
"aliases" : [ "CVE-2026-54136" ],
"summary" : "Windmill: Resource-scoped API tokens can read script contents outside their allowed path via scripts/list_search",
"details" : "### Summary\n\nA resource-scoped API token can read script contents outside its allowed path scope via `GET /api/w/{workspace}/scripts/list_search`.\n\nThis appears to be a remaining variant of the scoped-token authorization class previously addressed for other endpoints. The route-level scope middleware validates the token domain/action, but does not enforce the resource/path segment of a scope. `scripts/list_search` then returns script `path` and `content` for scripts in the workspace without applying per-row path filtering against the token scopes.\n\n### Affected endpoint\n\n`GET /api/w/{workspace}/scripts/list_search`\n\n### Affected versions\n\nConfirmed in the current public repository code and believed to affect the latest published release at the time of review:\n\n`<= 1.714.1`\n\nPatched version: unknown.\n\n### Details\n\nWindmill supports scoped API tokens with scopes in the format:\n\n`{domain}:{action}[:{resource}]`\n\nThe parser supports resource-scoped values such as:\n\n`scripts:read:f/allowed/*`\n\nand the codebase contains helpers for resource matching, including wildcard matching.\n\nHowever, the route-level scope check used for requests with scoped API tokens only validates the route domain and action. It does not compare the token's resource/path restriction against the requested route or against the rows returned by list endpoints.\n\nFor `scripts/list_search`, the handler returns `path` and `content` for scripts in the workspace:\n\n`SELECT path, content from script WHERE workspace_id = $1 AND archived = false LIMIT $2`\n\nThere is no additional `check_scopes(...)` call in the handler and no per-row filtering based on the token's resource/path scope.\n\nAs a result, a token intended to read only scripts under one path prefix may be able to read script contents from unrelated paths in the same workspace.\n\n### Source-level reproduction\n\n1. Create or use a workspace containing at least two scripts:\n\n- `f/allowed/script_a`\n- `f/private/script_b`\n\n2. Create a scoped API token intended to read only the allowed path:\n\n`scripts:read:f/allowed/*`\n\n3. Use that token to call:\n\n`GET /api/w/{workspace}/scripts/list_search`\n\n4. Expected behavior:\n\nThe response should include only scripts matching the token's resource scope, e.g. only scripts under:\n\n`f/allowed/*`\n\n5. Actual behavior from source review:\n\nThe route-level scope check accepts the request as `scripts:read`, and the handler returns script `path` and `content` for scripts in the workspace without filtering the rows by the token's resource scope.\n\nThis can expose script source code from paths outside the token's intended scope.\n\n### Impact\n\nA user or integration holding a path-restricted `scripts:read:{resource}` token may be able to read script contents from unrelated scripts in the same workspace.\n\nDepending on how scripts are used, this may disclose:\n\n- internal automation logic,\n- integration details,\n- business logic,\n- inline configuration,\n- accidentally hardcoded secrets or credentials.\n\nThis does not require admin privileges. It requires possession of a valid scoped API token for the workspace.\n\n### Related context\n\nThis appears related to the broader class of issues where route-level token scope enforcement validates domain/action but not the resource/path portion of the scope. Similar scoped-token issues appear to have been fixed for other endpoints, such as resources/variables listing and job preview/run paths, but I did not find an equivalent fix for `scripts/list_search`.\n\n### Suggested fix\n\nApply resource/path scope enforcement to `scripts/list_search`.\n\nPossible approaches:\n\n1. Add explicit handler-level authorization similar to per-resource endpoints.\n2. Filter returned rows so that a scoped token only receives scripts whose `path` is included by at least one `scripts:read:{resource}` scope.\n3. Add regression tests for:\n - `scripts:read:f/allowed/*` cannot see `f/private/script_b`,\n - broad `scripts:read` still sees all accessible scripts,\n - unscoped tokens preserve current behavior,\n - filter-tag-only tokens preserve current compatibility behavior.\n\nA more defensive long-term fix would be to make route-level scope enforcement aware of resource/path restrictions where the route contains a concrete resource path, while list endpoints should apply per-row filtering.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "crates.io",
"name" : "windmill-api"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "1.715.0"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 1.714.1"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/windmill-labs/windmill/security/advisories/GHSA-2ppx-66jv-wpw5"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/windmill-labs/windmill"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-863" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-10T19:28:06Z",
"nvd_published_at" : null
}
}