{"id":11785824,"name":"windmill-api","ecosystem":"cargo","description":"No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)","homepage":"https://windmill.dev","licenses":"Apache-2.0","normalized_licenses":["Apache-2.0"],"repository_url":"","keywords_array":[],"namespace":null,"versions_count":521,"first_release_published_at":"2025-06-10T11:33:52.998Z","latest_release_published_at":"2026-10-03T07:45:47.999Z","latest_release_number":"1.822.0","last_synced_at":"2026-10-05T09:10:26.101Z","created_at":"2025-06-10T11:45:41.870Z","updated_at":"2026-10-05T14:17:42.779Z","registry_url":"https://crates.io/crates/windmill-api/","install_command":"cargo install windmill-api","documentation_url":"https://docs.rs/windmill-api/","metadata":{"categories":[]},"repo_metadata":{},"repo_metadata_updated_at":"2026-10-04T09:08:43.058Z","dependent_packages_count":0,"downloads":46956,"downloads_period":"total","dependent_repos_count":0,"rankings":{"downloads":94.80737018425461,"dependent_repos_count":21.34874579294823,"dependent_packages_count":28.269832132800225,"stargazers_count":null,"forks_count":null,"docker_downloads_count":null,"average":48.14198270333435},"purl":"pkg:cargo/windmill-api","advisories":[{"uuid":"GSA_kwCzR0hTQS0ycHB4LTY2anYtd3B3Nc4ABahj","url":"https://github.com/advisories/GHSA-2ppx-66jv-wpw5","title":"Windmill: Resource-scoped API tokens can read script contents outside their allowed path via scripts/list_search","description":"### 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`\u003c= 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.","origin":"UNSPECIFIED","severity":"MODERATE","published_at":"2026-07-10T19:28:06.000Z","withdrawn_at":null,"classification":"GENERAL","cvss_score":5.1,"cvss_vector":"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","references":["https://github.com/windmill-labs/windmill/security/advisories/GHSA-2ppx-66jv-wpw5","https://github.com/advisories/GHSA-2ppx-66jv-wpw5"],"source_kind":"github","identifiers":["GHSA-2ppx-66jv-wpw5","CVE-2026-54136"],"repository_url":null,"blast_radius":0.0,"created_at":"2026-07-10T20:00:08.462Z","updated_at":"2026-10-05T13:01:45.367Z","epss_percentage":0.00473,"epss_percentile":0.38582,"api_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0ycHB4LTY2anYtd3B3Nc4ABahj","html_url":"https://advisories.ecosyste.ms/advisories/GSA_kwCzR0hTQS0ycHB4LTY2anYtd3B3Nc4ABahj","packages":[{"ecosystem":"cargo","package_name":"windmill-api","versions":[{"first_patched_version":"1.715.0","vulnerable_version_range":"\u003c= 1.714.1"}],"purl":"pkg:cargo/windmill-api"}],"related_packages_url":"https://advisories.ecosyste.ms/api/v1/advisories/GSA_kwCzR0hTQS0ycHB4LTY2anYtd3B3Nc4ABahj/related_packages","related_advisories":[]}],"docker_usage_url":"https://docker.ecosyste.ms/usage/cargo/windmill-api","docker_dependents_count":22,"docker_downloads_count":18696328,"usage_url":"https://repos.ecosyste.ms/usage/cargo/windmill-api","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/cargo/windmill-api/dependencies","status":null,"funding_links":[],"critical":null,"issue_metadata":null,"versions_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/packages/windmill-api/codemeta","maintainers":[{"uuid":"205717","login":"rubenfiszel","name":"Ruben Fiszel","email":null,"url":"https://github.com/rubenfiszel","packages_count":3,"html_url":"https://crates.io/users/rubenfiszel","role":null,"created_at":"2025-06-18T06:34:09.262Z","updated_at":"2025-06-18T06:34:09.262Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/crates.io/maintainers/rubenfiszel/packages"}]}