From eddb71354d252b8f03e98dae28d7500cf2a5a2be Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 3 Jan 2023 03:28:48 +0100 Subject: [PATCH] disallow loading public app if not visible anymore --- backend/windmill-api/src/apps.rs | 9 ++++ .../apps/editor/AppEditorHeader.svelte | 11 +++-- .../components/sidebar/WorkspaceMenu.svelte | 3 +- .../user/(user)/workspaces/+page.svelte | 2 +- .../[workspace]/[...secret]/+page.svelte | 42 ++++++++++++------- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/backend/windmill-api/src/apps.rs b/backend/windmill-api/src/apps.rs index d5a99263d6..82ce59f0ea 100644 --- a/backend/windmill-api/src/apps.rs +++ b/backend/windmill-api/src/apps.rs @@ -258,6 +258,15 @@ async fn get_public_app_by_secret( tx.commit().await?; let app = not_found_if_none(app_o, "App", id.to_string())?; + + let policy = serde_json::from_value::(app.policy.clone()).map_err(to_anyhow)?; + + if !matches!(policy.execution_mode, ExecutionMode::Anonymous) { + return Err(Error::NotAuthorized( + "App visibility does not allow public access".to_string(), + )); + } + Ok(Json(app)) } diff --git a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte index fb6c8797e9..ddd3464f1f 100644 --- a/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte +++ b/frontend/src/lib/components/apps/editor/AppEditorHeader.svelte @@ -162,10 +162,13 @@ Save this app once before you can publish it {:else} - Every runnable will run with the permissions of the publisher of the app. This ensures that - every users gets the same experience. Make sure that the app does not expose actions that - are too sensitive to be exposed publicly. + A viewer of the app will execute the runnables of the app on behalf of the publisher + avoiding the risk that a resource or script would not be available to the viewer. To + guarantee tight security, a policy is computed at time of saving of the app which only allow + the scripts/flows referred to in the app to be called on behalf of. Furthermore, static + parameters are not overridable. Hence, users will only be able to use the app as intended by + the publisher without risk for leaking resources not used in the app.
- import { workspaceStore, userWorkspaces, switchWorkspace } from '$lib/stores' + import { workspaceStore, userWorkspaces, switchWorkspace, usersWorkspaceStore } from '$lib/stores' import { classNames } from '$lib/utils' - import Icon from 'svelte-awesome' import { Building } from 'lucide-svelte' import Menu from '../common/menu/Menu.svelte' diff --git a/frontend/src/routes/(root)/(logged)/user/(user)/workspaces/+page.svelte b/frontend/src/routes/(root)/(logged)/user/(user)/workspaces/+page.svelte index 9e3115f656..1dba750990 100644 --- a/frontend/src/routes/(root)/(logged)/user/(user)/workspaces/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/user/(user)/workspaces/+page.svelte @@ -90,7 +90,7 @@ />
{/if} - {#if workspaces} + {#if workspaces && $usersWorkspaceStore} {#if workspaces.length == 0}

You are not a member of any workspace yet. Accept an invitation or create your own diff --git a/frontend/src/routes/public/[workspace]/[...secret]/+page.svelte b/frontend/src/routes/public/[workspace]/[...secret]/+page.svelte index 4e83d86b53..e1311c2455 100644 --- a/frontend/src/routes/public/[workspace]/[...secret]/+page.svelte +++ b/frontend/src/routes/public/[workspace]/[...secret]/+page.svelte @@ -4,7 +4,7 @@ import AppPreview from '$lib/components/apps/editor/AppPreview.svelte' import type { EditorBreakpoint } from '$lib/components/apps/types' - import { Skeleton } from '$lib/components/common' + import { Alert, Skeleton } from '$lib/components/common' import { WindmillIcon } from '$lib/components/icons' import { AppService, AppWithLastVersion, GlobalUserInfo, UserService } from '$lib/gen' import github from 'svelte-highlight/styles/github' @@ -12,12 +12,17 @@ let app: AppWithLastVersion | undefined = undefined let user: GlobalUserInfo | undefined = undefined + let notExists = false async function loadApp() { - app = await AppService.getPublicAppBySecret({ - workspace: $page.params.workspace, - path: $page.params.secret - }) + try { + app = await AppService.getPublicAppBySecret({ + workspace: $page.params.workspace, + path: $page.params.secret + }) + } catch (e) { + notExists = true + } } async function loadUser() { @@ -42,17 +47,24 @@ >Powered by   Windmill -{#if app} -

-
- {#if user} - Logged in as {user.email} - {:else} - Not logged in - {/if} -
- Go to app +
+
+ {#if user} + Logged in as {user.email} + {:else} + Not logged in + {/if}
+ Go to app +
+{#if notExists} +
There was an error loading the app. Either it does not exist at this url or its visibility + has changed to not be public anymore. Go to app +
+{:else if app}