diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index cff094ca35..142ca727a7 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -3489c243b0e5a8eb0dbc86e90917fbe72843573b +daffe7bb81cfcaca666c61de1ee838a44d60ebc2 diff --git a/backend/windmill-api/src/triggers/http/handler.rs b/backend/windmill-api/src/triggers/http/handler.rs index ccde55bab1..ffb61e31fa 100644 --- a/backend/windmill-api/src/triggers/http/handler.rs +++ b/backend/windmill-api/src/triggers/http/handler.rs @@ -424,6 +424,7 @@ async fn route_job( .flatten() .unwrap_or("application/octet-stream".parse().unwrap()), ); + response_headers.insert("x-content-type-options", "nosniff".parse().unwrap()); if !trigger.is_static_website { response_headers.insert( "content-disposition", @@ -443,6 +444,19 @@ async fn route_job( }, ), ); + // For single-file triggers, sandbox any HTML/SVG so it can't + // reach the viewer's session cookie. Allow-scripts/forms/etc. + // keep the opaque origin (cookies still blocked) while + // preserving JS for legitimate HTML payloads. Static-website + // triggers intentionally serve a live web app and cannot be + // sandboxed; restrict write access to those buckets at the + // workspace level. + response_headers.insert( + "content-security-policy", + "sandbox allow-scripts allow-forms allow-popups allow-modals allow-downloads" + .parse() + .unwrap(), + ); } let body_stream = axum::body::Body::from_stream(s3_object.into_stream());