* [ee] fix(s3): sandbox stored XSS via download response headers
Reported chain: a workspace user uploads xss.html via
apps_u/upload_s3_file with content_type=text/html&content_disposition=inline;
when an admin clicks the resulting download URL the browser renders
the attacker page in Windmill's origin and can escalate via the
SameSite=Lax session cookie.
Fix on the download side only — leaves upload semantics unchanged so
existing integrations are not affected:
- download_s3_file_internal (used by apps_u/download_s3_file and
job_helpers/download_s3_file) emits X-Content-Type-Options: nosniff
and Content-Security-Policy: sandbox on every response (EE).
- The HTTP static-asset trigger emits the same headers on single-file
responses. Static-website responses keep their existing semantics
(CSP sandbox would break a legitimate static site); restricting
write access to those buckets remains the documented mitigation.
Sandbox loads any HTML/SVG into an opaque origin so the page cannot
reach the viewer's cookie or /api/*. Images, PDFs, and fetch-driven
previews are unaffected (browsers ignore CSP for <img>/<embed> and
for fetch responses).
Companion: windmill-ee-private fix/s3-content-type-xss.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to daffe7bb81cfcaca666c61de1ee838a44d60ebc2
This commit updates the EE repository reference after PR #585 was merged in windmill-ee-private.
Previous ee-repo-ref: e889b86ee1c68c2f7cf9b07ec4b8ba6e6b66a169
New ee-repo-ref: daffe7bb81cfcaca666c61de1ee838a44d60ebc2
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* stash
* ui nits
* Fix contenteditable feedback look (duplicate typing)
* fix right icon wrong position with placeholder
* user editor in Path editor takes correct width
* nits
* nit
* chore: remove assets-operator changes (moved to separate PR)
These files were mistakenly included in this PR and belong in a dedicated PR
("Allow assets page to operators").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: remove sidebar assets-operator change (moved to separate PR)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix disabled
* border nit
* Fix disabled styling
* Apply suggestion from @cubic-dev-ai[bot]
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* nit
* Update frontend/src/lib/components/text_input/TextInput.svelte
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Fix disabled tabindex and aria-disabled on contenteditable Select
The useContentEditable branch had an unconditional tabindex="0", keeping
a disabled Select in the tab order, and was missing aria-disabled.
Mirror the TextInput div branch.
Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
* fix: drop obsolete hideFullPath prop from EditorHeader Path usage
* invalidate autocomplete paths on deploy
* nit pixel
* use Badge in auto complete
* nit prevent default
* fix(autocomplete): don't let stale fetch clobber forced refresh
A non-forced fetchWorkspacePaths() that started before invalidateWorkspacePaths()
could still resolve afterward, overwrite the cache, and clear forceNextFetch —
making the post-deploy refresh a no-op. Only write back from the promise that
is still the current pending one, and only clear the force flag when the
completing fetch was itself forced.
* refactor(path): drop unreachable 'group' branch in owner-kind setter
The Select only offers user/folder, so the 'group' branch was dead. Leave a
short note pointing at validateName which still accepts 'group' for
forward-compat.
* fix(path): respect disableEditing on owner-kind selector
Other path-editor controls disable on (disabled || disableEditing); the
owner-kind Select only checked `disabled`, so read-only users (trigger
editors with !can_write) could still toggle User/Folder and mutate the
bound path. Reuse the existing nameDisabled flag.
* Revert "fix(autocomplete): don't let stale fetch clobber forced refresh"
This reverts commit 6649975714.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Diego Imbert <diegoimbert@users.noreply.github.com>
* feat(nsjail): make tmpfs size configurable via instance setting
Adds a new `nsjail_tmpfs_size_mb` instance setting that overrides the
size of the `/tmp` tmpfs mount inside the nsjail sandbox across all
languages. When unset, the existing per-language defaults (500MB or
800MB) continue to apply, so no behavior change for existing
deployments.
The setting is exposed under Settings → Jobs and is read at job
execution time, so changes take effect on the next job without a
restart.
Fixes WIN-1963
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(nsjail): unify default tmpfs size to 800MB
Previously each executor passed its own per-language default (500MB or
800MB) to resolve_nsjail_tmpfs_size. Unify on a single
DEFAULT_NSJAIL_TMPFS_SIZE_BYTES constant (800MB) so the placeholder
behavior is consistent across languages.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(nsjail): resolve tmpfs size outside ruby download closure
The download.ruby config render runs inside a sync closure passed to
par_install_language_dependencies_seq, so `.await` on
resolve_nsjail_tmpfs_size() was a compile error under the `ruby`
feature. Resolve the size once before the closure and capture the
string instead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(nsjail): rename resolver to *_bytes and clarify fallback
Addresses CI review feedback:
- Rename `resolve_nsjail_tmpfs_size` to `resolve_nsjail_tmpfs_size_bytes`
so the returned unit is unambiguous at the call site (cubic P2).
- Fix the `NSJAIL_TMPFS_SIZE_MB` doc comment that still said "per-language
default" — there is no per-language fallback anymore, all unset
values resolve to the unified 800MB `DEFAULT_NSJAIL_TMPFS_SIZE_BYTES`
(codex/pi P2).
- Expand the resolver doc to call out that `Some(0)` and negative values
also fall back, since the match arm is `Some(mb) if mb > 0`.
No behavior change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [ee] fix(saml): preserve deep links from /a/[...path] across SAML round-trip
Fixes WIN-1962.
PR #9225 only covered users who pass through /user/login on their way to
the IdP — that's where `redirectSaml()` runs and where the deep link gets
stuffed into `RelayState`. The reported flow doesn't go through that
page: it hits `/a/[...path]` (the public-app custom-path route, outside
the `(logged)` layout) where `PublicApp.svelte` renders its own `<Login>`
and was passing `page.url.toString()` as `rd` — the full URL.
Three problems compounded:
1. `redirectSaml()` only set `RelayState` when `rd.startsWith('/')`,
so a full URL silently fell through and the deep link was lost.
The IdP echoed back the SP-library default (BASE_URL), which the
ACS validator correctly rejected as a potential open-redirect.
2. `persistRd()` stored the full URL in `localStorage.rd`. On the
fallback landing at `/user/login`, the post-login redirect saw
an `http://...` value, hit the cross-origin branch, and bounced
to `/` — which from a logged-in but workspace-less state shows
the "Loading user…" modal forever (bug 2).
3. The EE `safe_relay_state_redirect` validator rejected any full
URL, including same-origin ones, so even IdPs that prepend the
origin or that pass a configured absolute deep link via
IdP-initiated SSO got dropped on the floor.
The fix is a single concept applied at every layer: reduce a redirect
target to a safe same-origin relative path, or refuse it.
Frontend:
- `logoutRedirect.ts`: new `toSameOriginRelativePath(rd)` helper that
accepts both `/foo` and `https://current-origin/foo`, with the same
open-redirect guards as the backend (length cap, control chars, no
protocol-relative or back-slash tricks). Returns `null` for
cross-origin or malformed input.
- `PublicApp.svelte`: pass `pathname + search + hash` to `<Login>`
instead of the full URL — this alone fixes the happy path.
- `Login.svelte`: `redirectSaml()`, `persistRd()`, and `redirectUser()`
all route through the helper, so full URLs from `/a/[...path]` are
reduced before being put in `RelayState`/`localStorage`/`goto()`.
- `/user/login/+page.svelte`: the same reduction is applied to the
resolved `rd` so any stale full-URL value in `localStorage.rd` still
navigates to the intended page instead of falling into the
cross-origin branch.
Backend (EE companion: windmill-ee-private#TBD):
- `safe_relay_state_redirect` now reduces a `RelayState` whose origin
matches `BASE_URL` to its path before applying the same-origin path
safety rules. Bare BASE_URL with no path still falls back to
`/user/login` (no useful deep link to honor).
- New `same_origin_relative_path` helper + expanded unit tests.
Test plan:
- [x] Frontend: `vitest run src/lib/logoutRedirect.test.ts` — 9 passed
- [x] Backend: `cargo test -p windmill-api ... saml_ee::tests` — 3 passed
(`honors_same_origin_relative_path`, `reduces_same_origin_full_url_to_path`,
`falls_back_on_open_redirect_attempts`)
- [ ] Manual e2e (needs configured SAML IdP — not on local CE):
- Unauthenticated visit to `/a/<path>` → click SSO → SAML → land on
`/a/<path>` (RelayState now carries the relative path).
- IdP that echoes BASE_URL as default → ACS still falls back to
`/user/login` (no useful path to honor), but the page no longer
hangs: the stale full-URL `localStorage.rd` is reduced to its path
and the post-login redirect navigates to it.
- Tampered `RelayState` (`//evil.com`, `https://evil.com/x`) → ACS
rejects, lands on `/user/login`.
* chore: update ee-repo-ref to 3489c243b0e5a8eb0dbc86e90917fbe72843573b
This commit updates the EE repository reference after PR #584 was merged in windmill-ee-private.
Previous ee-repo-ref: 635ff3eeb8e47bb84d5686942605f67f8f6224b4
New ee-repo-ref: 3489c243b0e5a8eb0dbc86e90917fbe72843573b
Automated by sync-ee-ref workflow.
---------
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* feat: thread temp_script_refs into preview jobs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: resolve python preview relative imports from temp script refs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: use local relative imports in wmill script preview
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: use local relative imports in wmill flow preview
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: add temp_script_refs to Preview and FlowPreview openapi schemas
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: pass temp_script_refs to bun lockfile gen for no-lock preview
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: route script preview through shared buildPreviewTempScriptRefs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: resolve local relative imports in wmill app dev inline scripts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: address cubic review — bundle cache key, preview-mode gate, error masking
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* perf: skip dep-tree build when previewed script has no relative imports; narrow old-backend classifier
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: address review issues (preview-only gate, bundle preview, app dev cwd)
Three P1s flagged in repeated codex/pi reviews on PR #9233:
- Gate _TEMP_SCRIPT_REFS extraction on JobKind::Preview (bun + python
executors) and propagation in worker_flow on JobKind::FlowPreview. job.args
includes caller-controlled request args, so honoring this key on deployed
runs would let a caller swap import resolution to local content uploaded
via /raw_temp.
- run_bundle_preview_script now injects temp_script_refs into PushArgs.extra,
mirroring run_preview_script — closes the silent data drop for the bundle
preview path.
- wmill app dev chdirs to the wmill.yaml root before buildPreviewTempScriptRefs
and restores after, so the `cd <app>__raw_app && wmill app dev` invocation
(cwd is the raw_app folder, no app_folder arg) still walks sibling workspace
scripts like f/lib.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(ee): bump ee-repo-ref to 5b347d6 (handle_python_deps arity fix)
Picks up the EE arity fix so cargo_test + check_ee_full compile cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(ee): bump ee-repo-ref to 52e273d (agent-workers bundle path arity fix)
Picks up windmill-ee-private 52e273d which adds the missing &None arg to
compute_bundle_local_and_remote_path in windmill-api-agent-workers/src/ee.rs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(ee): bump ee-repo-ref to 2d6ffd3 (EE main merged in)
Previous bump pinned an older EE commit, missing the audit-log object-store
export module (EE PR #579, commit ec3cd35) and other EE main updates. The
CE backend's `crate::ee_oss::anchor_audit_logs_s3_checkpoint_env_var` and
`export_audit_logs_to_object_store` references need the new EE definitions.
Merged origin/main into the EE branch and pinned the merge commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to b0c87b1272c25dca4aa9148c87fb024a9d9ef322
This commit updates the EE repository reference after PR #583 was merged in windmill-ee-private.
Previous ee-repo-ref: 2d6ffd32c99bd93e79cf78675cb89499a81b17e1
New ee-repo-ref: b0c87b1272c25dca4aa9148c87fb024a9d9ef322
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* [ee] fix(autoscaling): only divide native_mode pings by NUM_WORKERS
#9020 / EE #548 changed worker counting to COUNT(DISTINCT worker_instance) to
fix native-mode over-counting (NUM_WORKERS=8 pings per pod). That collapsed
custom worker groups that share a hostname across multiple worker processes
to a count of 1, breaking their autoscaling.
EE fix uses the per-ping native_mode flag: divide native rows by 8 (CEIL),
count non-native rows as-is.
Companion EE PR: windmill-labs/windmill-ee-private#fix-autoscaling-custom-worker-group-count
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to abeb405de36a3fe23382f19e762268f87b6679be
This commit updates the EE repository reference after PR #582 was merged in windmill-ee-private.
Previous ee-repo-ref: 135db676843346ed6e3015232161a49c3ce01db5
New ee-repo-ref: abeb405de36a3fe23382f19e762268f87b6679be
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* feat(snowflake): derive public key from private key when omitted (WIN-1959)
Snowflake key-pair auth needs a SHA256 fingerprint of the public key for
the JWT iss claim, but the public key is mathematically derivable from
the RSA private key. Other tools (e.g. Power BI) only require the
private key, so requiring users to supply both is redundant. When
public_key is missing, fall back to deriving it from private_key (PKCS#8
or PKCS#1 PEM) instead of erroring out.
Fixes WIN-1959
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(snowflake): treat empty public_key/private_key as missing
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(vault): add optional KV secret path prefix setting (WIN-1960)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to 0189ba6504fd70eb4929e4881d624d48efd14aee
This commit updates the EE repository reference after PR #581 was merged in windmill-ee-private.
Previous ee-repo-ref: e32e8d6483550c67897e09b6f900dff1034bdae8
New ee-repo-ref: 0189ba6504fd70eb4929e4881d624d48efd14aee
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: enforce auth guards on app component preview execution
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: guard previewed runnable path and worker tag in app preview
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: validate app_script id ownership and keep root push isolation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: scope app preview guards to operator check + referenced runnables
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: require jobs:run scope and tag check on app preview (apps:run escalation)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* [ee] feat(indexer): observability for unavailable search index
A user hit `Not found: There is no index reader to search from` when
searching service logs and could not tell whether it was a config
error or a bug, and asked for visibility into the indexer status
(WIN-1956).
Backend (EE companion PR):
- Replace the opaque error with an actionable message explaining the
likely causes (indexer disabled, still starting, or blocked
acquiring the indexer lock) and pointing to the status panel.
- Add a coarse `state` (running | stale | never_started) to
`/indexer/status`, derived from the lock row, distinguishing a
never-configured indexer from a stale/blocked one.
Frontend:
- Instance Settings > Indexer now shows Running / Stale / Not started
with a tooltip explaining what to check for each.
- Service logs search now catches failures and shows an inline,
actionable Alert instead of an unhandled rejection.
Fixes WIN-1956
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to 017d36418a65ce5c840c502e3174df0c393612ba
This commit updates the EE repository reference after PR #580 was merged in windmill-ee-private.
Previous ee-repo-ref: 18b7e1b30a1ff582c4a072580bbb8aec34e22cdc
New ee-repo-ref: 017d36418a65ce5c840c502e3174df0c393612ba
Automated by sync-ee-ref workflow.
* fix(indexer): address review nits
- IndexerMemorySettings: older backends without `state` reporting
`is_alive: false` now show "Stopped" (red) again instead of
falling through to "Unknown" (codex/cubic P2).
- ServiceLogsInner: clear stale logs/counts on a failed search so the
error isn't shown alongside results from a previous query (codex P2).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix(frontend): open customer portal in popup synchronously to bypass Safari blocker
Safari blocks window.open() called after an await because it loses the
user-gesture context. Open a blank tab synchronously on click, then
assign location.href once the portal URL resolves.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(backend): wire dev_override feature flag in backend crate
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: export audit logs to dedicated object store folder
* fix: gap-free audit export via snapshot-xmin gate and stable object keys
* test: add integration test for audit log object store exporter
* fix: cursor audit export on snapshot xmin to prevent id-leapfrog loss
* fix: protect audit s3 checkpoint from config sync and bound export interval
* fix: anchor audit s3 checkpoint at enable time to not skip first-window rows
* fix: anchor first audit export at the enable transaction's xid
* fix: use epoch timestamp floor on first audit export run to not drop old backlog
* fix: anchor audit export at startup for env-var enable path
* fix: anchor audit export via enabling-txn snapshot xmin trigger
* fix: bound the bootstrap audit export to MAX_XID_INTERVAL per tick
* refactor: store audit export cursor in background_task_state, add status endpoint
* docs: align store_audit_logs_s3 setting text with the actual enable-boundary contract
* [ee] refactor: move audit s3 export core logic to EE, gate on Enterprise license
* chore: update ee-repo-ref to ec3cd353245e1cdf6a290528dbd7f2ac2498386c
This commit updates the EE repository reference after PR #579 was merged in windmill-ee-private.
Previous ee-repo-ref: 4ffc6d5f874e64d7dc4a147b4e73baa6c44867a5
New ee-repo-ref: ec3cd353245e1cdf6a290528dbd7f2ac2498386c
Automated by sync-ee-ref workflow.
---------
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix(autoscaling): full-scale from below min_workers when backlog exceeds threshold
Bump EE ref to pull in the autoscaling fix: when active worker count is
below min_workers and a relevant tag's queue depth already exceeds
full_scale_jobs_waiting, scale straight to max_workers instead of slowly
ramping to min_workers first.
Companion EE PR: windmill-labs/windmill-ee-private#improve-pr-9209
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to b4d68e40430cf0300b5d37734d1505fd743f1059
This commit updates the EE repository reference after PR #578 was merged in windmill-ee-private.
Previous ee-repo-ref: 99810eb763703ef0f4b3311338e0e65f53544158
New ee-repo-ref: b4d68e40430cf0300b5d37734d1505fd743f1059
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: enable jemalloc background purge to prevent worker RSS growth
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: drop decay overrides, keep only jemalloc background_thread
The background thread is the actual fix; jemalloc's default decay
windows (dirty 10s, muzzy 0) are correct for months-long workers and
muzzy_decay_ms:5000 was more retentive than the default.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: advance postgres replication slot lsn via periodic standby status updates
* test: add e2e regression test for postgres replication slot lsn advancement
Drives sustained change traffic so the slot freeze reproduces deterministically (fails pre-fix at the 20s deadline, passes post-fix within ~10s). Also wires the postgres_trigger feature through windmill-test-utils and the integration-tests crate so the postgres trigger e2e tests are actually runnable.
* fix: honor SAML RelayState to redirect to deep link after SSO login
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: bump ee-repo-ref for SAML RelayState validator test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: update ee-repo-ref to a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206
This commit updates the EE repository reference after PR #577 was merged in windmill-ee-private.
Previous ee-repo-ref: 445a22536b1a6c342cde0baa6fbca9e25092f94b
New ee-repo-ref: a3fefe85f5f2f52bb473fa47acc9efa8fd0b2206
Automated by sync-ee-ref workflow.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
* fix: reject path traversal in MCP endpoint path parameters
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: narrow MCP path-param validator to structural escapes only
Codex review: rejecting whitespace/`:`/`@` regressed legitimate
Windmill paths (app paths with spaces, email-style usernames like
u/admin@windmill.dev/...). These are ordinary path-segment data in an
absolute URL and cannot redirect the request. Reject only structural
escapes: control chars, `\`, `%`, `?`, `#`, and `.`/`..`/empty segments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the Docusign Authorization Code OAuth entry. Used by the
Docusign integration in the windmill-integrations hub (PR #128).
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix: enforce jobs:run scope on job preview and inline endpoints
Preview/inline endpoints (run/preview, run/preview_bundle, run/preview_flow,
run/dynamic_select inline) execute arbitrary request-supplied code but only
checked folder/namespace read access, which is a no-op when path is null. A
token scoped to a specific script/flow could escape its scope and run any
code. Add a jobs:run scope check, matching other arbitrary-execution
endpoints. Advisory GHSA-vxc5-w28p-m9xw.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: scope-check dynamic_select flow branch and inline preview
Address CI review: the dynamic_select Deployed{Flow} branch ran a deployed
flow's dynamic-select code without any scope check (only the Script branch
delegated to a scope-checked handler), and run_inline_preview_script executed
request-supplied code with no in-handler scope check. Add jobs:run:flows:{path}
to the flow branch and jobs:run to inline preview; correct the misleading
comment. Expand regression tests (preview_flow case, assert success for the
broad-token case). Advisory GHSA-vxc5-w28p-m9xw.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: remove preview scope enforcement test after local validation
The regression test passed locally (3/3) and validated the fix end-to-end;
removed from the PR per maintainer preference. Advisory GHSA-vxc5-w28p-m9xw.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: constrain unauthenticated get_public_resource to app_theme resources
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: remove get_public_resource regression test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: bind /etc resolver files read-only in nsjail sandboxes
* docs(nsjail): explain why per-file /etc resolver binds are load-bearing
The explicit /etc/hosts, /etc/resolv.conf and /etc/hostname binds look
like removable duplication of the read-only /etc bind above them. They
are not: on Kubernetes those files are separate kubelet bind-mounts on
top of /etc and nsjail's read-only remount is non-recursive, so without
these shadow binds they stay writable and a job can persist cross-tenant
DNS poisoning for the pod lifetime. Comment guards against a future
"dedup cleanup" silently reintroducing the vulnerability.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs(nsjail): shorten the load-bearing-bind comment to 3 lines
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: reset parent_hash in auto_parent when all versions at path are archived
* test: regression test for auto_parent with all versions archived
---------
Co-authored-by: windmill-internal-app[bot] <1429786+windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
* fix: don't show ALLOW_PRIVATE_AI_BASE_URLS hint for malformed AI base URLs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: impl std::error::Error for SsrfValidationError for anyhow callers
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix: atomic bundle cache writes to prevent parallel cold-load race
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: trust-but-replace in atomic_publish_dir to never trust a stale partial cache dir
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: simplify atomic_publish_dir and add content-addressed rename-failure fallback
Revert the destroy-then-recreate dir swap (introduced concurrent-publisher
edge cases: spurious Err under a real herd, EACCES masking a stale partial)
back to a single atomic rename. Add the content-addressed exists-fallback to
atomic_write_file_bytes/atomic_copy_file so the loser of a publish race (and
Windows, where rename cannot replace an open/existing destination) treats the
already-published identical cache as success instead of failing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
windmill-parser-ts-asset only recognized writeS3File/loadS3File when
the first arg was a bare 's3://...' string literal. The actual SDK
signature takes an S3Object ({ s3, storage? }) or 's3://bucket/key'
string, which every real script uses, so object-form writes/reads were
never detected as assets. Resolve the S3Object arg the same way the
runtime parseS3Object does, mapping { s3, storage } to s3://<storage>/
<key> and feeding it through parse_asset_syntax so the path matches the
// on s3:///… trigger form. Adds regression tests.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: aggregate wait time should target the true root job, not flow_innermost_root_job
* refactor: reuse get_root_job_id helper for wait-time aggregation
Instead of duplicating the root_job → flow_innermost_root_job →
parent_job fallback chain inline, call the existing get_root_job_id()
helper (the same one used by push_next_flow_job) and filter out the
self-id case so standalone scripts still skip aggregate insertion.
Behaviorally identical, single source of truth.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: windmill-internal-app[bot] <1429786+windmill-internal-app[bot]@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>