Skip to content

feat(den): deploy environment variables to desktop agents - #6403

Open
OmarMcAdam wants to merge 12 commits into
devfrom
environment-variables
Open

OmarMcAdam wants to merge 12 commits into
devfrom
environment-variables

Conversation

@OmarMcAdam

Copy link
Copy Markdown
Member

What is this about?

Admins deploy environment variables from OpenWork Cloud (Manage › Environment Variables) to people's desktop agents.

What problem does it solve?

There was no way to give a team's agents a shared key, URL or setting, or to change or revoke it centrally.

What was the situation before?

Settings › Environment only held variables saved on that device.

How is this implemented?

  • Den (routes/org/environment-variables.ts): each assignment (everyone, team, person) holds its own encrypted value, or each person sets their own; people choose between assignments. Agents write values only after confirming, never read them; only the desktop receives values. New environment_variables.view/.manage permissions (admins by default). All changes audited without values.
  • Den web: editor with inline values per assignment; members get My Variables.
  • Desktop (cloud-environment-sync.ts): v1 starts a standby engine with the values; v2 applies them live via the session bridge and a shell hook (opencode-plugin/src/desktop-environment.ts). Settings shows them with Managed in Den badges.
  • Behind environmentVariables (cloud and self-hosted, off); turning it off removes values from agents on the next sync.

What else changed?

  • Fixed AutoAccessWallNotice dropping workspaceId (desktop typecheck failed on dev).

Release note

Admins can deploy environment variables to their team's agents from OpenWork Cloud, per team or person, or let each person set their own.

Evidence

No E2E spec. ee/apps/den-api/test/api/environment-variables.api.test.ts and apps/server/test/cloud-environment-native.test.ts (real OpenCode 2.0.26: a running engine's shells get a changed value and lose a removed one). Driven end to end on Daytona; screenshots in a comment.

Design: P1, P4, P9, P11, S2, S7, C5

Admins deploy environment variables to everyone, teams or people, each
assignment with its own value, or let each person set their own. Desktops add
them to the agent's environment: live on OpenCode v2 through the session
bridge, through a standby engine on v1. Agents can write values after explicit
confirmation but never read them. Every change is audited without values.

Behind environmentVariables (cloud and self-hosted, off).
AutoAccessWallNotice typed workspaceId but never destructured it, so the
desktop typecheck failed and Sign in lost the workspace.
…picker

The menu was pinned to the trigger's width, cutting off "Everyone in …"
assignment names. It now fits its labels, capped to the window.
Settings showed the last background sync, so a variable an admin had just
deployed (or the flag just turned on) appeared only up to five minutes later.
@mintlify

mintlify Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
differentai 🟢 Ready View Preview Oct 23, 2026, 5:48 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
openwork-app Ready Ready Preview Oct 23, 2026 5:49pm UTC
openwork-den Ready Ready Preview Oct 23, 2026 5:49pm UTC
openwork-diagnostics Ready Ready Preview Oct 23, 2026 5:49pm UTC
openwork-landing Ready Ready Preview, v0 Oct 23, 2026 5:49pm UTC

Request Review

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

OpenWork evidence

Status Commit Preview Updated
🟢 Ready · evidence passed efd551a Open preview 2026-10-23 17:59:40 UTC

Run details · Open the preview to inspect evidence and sandbox options.

@OmarMcAdam

Copy link
Copy Markdown
Member Author

Driven end to end on Daytona (preview-full, this branch). Engine checks read the running OpenCode process's environment in the desktop sandbox.

  • Admin editor: who receives it, each with its own value
    Den editor
  • Admin list
    Den list
  • A member's My Variables: own value, choice between assignments, locked admin value
    Member view
  • Desktop Settings › Environment: Managed in Den badges, locked admin values, own value, assignment picker
    Desktop settings
    Assignment picker
  • A local variable can't shadow an organization key
    Local conflict
  • Flag off: entries hidden, plain notice; the desktop removed every value on its next sync
    Flag off

Journeys checked on Daytona: flag off hides routes and agent tools; admin creates variables (everyone/team/person values, per-person); owner gets the direct value, member the team value; member picks another assignment; member and agent set own values (agent needs confirmed, then replaceExisting); agents can't read values; admin's agent must confirm replacements; desktop engine restarted with the new values after a choice, after saving an own value, after an admin edit (next sync), and after a new variable when Settings opened; flag off removed them, flag on restored them.

@vercel
vercel Bot temporarily deployed to Preview – openwork-landing October 23, 2026 00:58 Inactive
@vercel
vercel Bot temporarily deployed to Preview – openwork-diagnostics October 23, 2026 00:58 Inactive
@vercel
vercel Bot temporarily deployed to Preview – openwork-app October 23, 2026 00:58 Inactive
@OmarMcAdam
OmarMcAdam deployed to pr-internal-specs October 23, 2026 00:58 — with GitHub Actions Active
@diff-warden

diff-warden Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Warden: not approved

Security review found 2 high severity findings. Fix them and push; Warden reviews again automatically. If they are false positives, a maintainer can approve by hand.

Security findings (2 findings)

high: Cloud-managed secrets are exposed to model-controlled shell tools in `apps/server/src/engine-v2-preview.ts:600`
Resolved organization values are added to the v2 engine process environment and copied into new shell environments. When shell use is allowed or approved, model-controlled commands can print those values into tool output returned to the model, or send them over the network. This bypasses Den’s restriction that agents cannot read resolved values. Keep the secrets out of general-purpose model-invoked processes. Clear when: model-invoked shells and other tool processes cannot read deployed secret values.
high: MCP callers can self-confirm environment deployments in `ee/apps/den-api/src/routes/org/environment-variables.ts:666`
Replace the caller-supplied `confirmed` flag with a user-side approval bound to the planned assignments; an MCP agent can set this flag itself and deploy values without the person's approval.

Reviewed efd551ae6f5e · Warden run · Updates after every Warden run.

@github-actions
github-actions Bot temporarily deployed to Evidence / PR 6403 October 23, 2026 01:09 Inactive
Address review findings and CI:
- Refuse keys that make tools run other commands (GIT_*, LD_*, DYLD_*,
  shell startup, interpreter and package-manager config) in Den, and drop
  them again on the desktop.
- Key the desktop's cached values by Den identity and clear the server's
  values whenever the session changes, so another account's values never
  render.
- Build @openwork/types/den/environment-variables to JavaScript: the
  packaged server can't load TypeScript from node_modules.
- Declare the Environment Variables OpenAPI tag and mark timestamps as
  date-time.
@OmarMcAdam

Copy link
Copy Markdown
Member Author

Warden findings, addressed in c5afbc4:

  • Cached values after an account switch (high): fixed. The desktop's cache is keyed by the verified Den identity (person + organization), other identities' entries are removed on sign-out or switch, and nothing is fetched or shown while signed out. The desktop server also clears its values on any session change, before fetching the new account's. Covered by apps/server/test/cloud-environment-sync.test.ts.
  • GIT_CONFIG_* can run commands (high): fixed. Den refuses keys that make programs load or run other code: GIT_*, LD_*, DYLD_*, BASH_FUNC_*, shell startup (BASH_ENV, ENV, PROMPT_COMMAND, …), interpreter options (PYTHONSTARTUP, PERL5OPT, JAVA_TOOL_OPTIONS, …), package-manager config and editors/pagers. The desktop drops the same keys again, so an older Den can't deliver them. Covered by ee/apps/den-api/test/environment-variables.test.ts and the server test.
  • Agent shells can read values (high): intended. Delivering values into the agent's environment so its tools (CLIs, scripts, MCP servers) can use them is the feature. This is the same as the existing per-device variables in Settings › Environment and provider credentials. What stays closed: agents can't read values through Den (/resolved is x-mcp: false and refuses agents and API keys), lists never include values, and admin-set values are never shown in any UI. Admins choose what to deploy and to whom; the feature is off by default behind environmentVariables. Needs a maintainer's approval as a false positive.
  • Confirmation flags (low): intended. Agents writing a member's own value after explicit confirmation (and a second confirmation to replace one) is the requested behavior. The impact is limited to the caller's own per-member values, every write is audited, and the person can always use the private field (postEnvironmentVariablesValuePrompt) instead.

…n account switch

- Refuse TAR_OPTIONS and other option variables tools read as flags (make,
  rsync, less, prompts) and more editors and pagers.
- On a Den session change, start an engine without the previous person's
  values before fetching the new account's, so a failed fetch can't leave
  them running.
- Use role-only names for test users.
@OmarMcAdam

Copy link
Copy Markdown
Member Author

Second Warden round, addressed in 2413105:

  • TAR_OPTIONS bypass (high): fixed. Also refused: other option variables tools read as flags (MAKEFLAGS/MFLAGS/GNUMAKEFLAGS, RSYNC_*, CVS_RSH, SVN_SSH, LESS/LESSKEY*, MANOPT, FPATH, PS0–PS3), and more editors, pagers and terminals (HG*, FCEDIT, SYSTEMD_PAGER, PSQL_PAGER, …). The desktop applies the same rule.
  • Failed fetch after an account switch (high): fixed. On any Den session change the desktop now starts an engine without the previous values before it fetches the new account's, so a failed fetch can't leave them running. Covered by apps/server/test/cloud-environment-sync.test.ts.
  • Confidentiality (2 items): no real people, customers or contacts are in this PR. The test users had invented first names, which I've replaced with role-only labels ("Design Member", "Agents Owner", …). Emails and URLs only use reserved test domains (example.test, .example).
  • Agent commands inherit values (high) and self-asserted confirmation (low): unchanged and intended, as explained in my previous comment. Delivering values to the agent's tools is the feature (same as existing per-device variables), and agents setting a member's own value after confirming is the requested behavior. These need a maintainer's decision.

@vercel
vercel Bot temporarily deployed to Preview – openwork-landing October 23, 2026 16:36 Inactive
# Conflicts:
#	ee/packages/den-db/drizzle/meta/0156_snapshot.json
#	ee/packages/den-db/drizzle/meta/_journal.json
#	ee/packages/utils/src/typeid.ts
#	packages/docs/openapi.json
#	packages/features/src/registry.ts
#	packages/sdk/src/gen/sdk.gen.ts
#	packages/sdk/src/gen/types.gen.ts
#	packages/types/package.json
#	packages/types/tsup.config.ts
#	packaging/helm/openwork-ee/values.schema.json
#	packaging/helm/openwork-ee/values.yaml
…o the Den account

- Refuse VIMINIT, EXINIT, GVIMINIT, MYVIMRC, NVIM_* and other editor
  startup variables.
- Key the agent's list of variable names by the signed-in organization and
  account, so names from one organization are never reused after a switch.
@vercel
vercel Bot temporarily deployed to Preview – openwork-landing October 23, 2026 17:29 Inactive
@OmarMcAdam

Copy link
Copy Markdown
Member Author

Third Warden round, addressed in 04280fa:

  • VIMINIT/EXINIT (high): fixed. Also refused: GVIMINIT, MYVIMRC, MYGVIMRC, VIMRUNTIME, VIM, NVIM_*, EMACSLOADPATH, EMACSNATIVELOADPATH, INPUTRC. Same rule on the desktop.
  • Variable names cached across organization switches (medium): fixed. The agent's list of variable names is now cached per signed-in organization and account (a fingerprint, not the token), so names from one organization are never reused after a switch. The desktop server already clears the values themselves on any session change.
  • Values reach agent shells (high): unchanged and intended, as explained in the earlier comments. Delivering values to the agent's tools is the feature; agents can't read them through Den. This needs a maintainer's decision.

…akening keys

- Creating or updating a variable with values from an agent or API key
  now needs confirmed: true, like members' own values.
- Refuse NODE_TLS_*, SSL_*, SSLKEYLOGFILE and CA bundle overrides.
@OmarMcAdam

Copy link
Copy Markdown
Member Author

Fourth Warden round, addressed in e0758e7:

  • Machine callers create values without confirmation (high): fixed. Creating or updating a variable with values from an agent or API key now needs confirmed: true (409 confirmation_required with the affected assignments otherwise); replacing stored values still also needs replaceExisting: true. Covered in ee/apps/den-api/test/api/environment-variables.api.test.ts. TLS-weakening keys are refused too (NODE_TLS_*, SSL_*, SSLKEYLOGFILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, AWS_CA_BUNDLE, PYTHONHTTPSVERIFY, …), so a deployed proxy can't be combined with disabled certificate checks.
  • Project plugins can read the snapshot via the broker (high), member sessions can fetch /resolved (high) and agent shells can read values (high): these are one property of the feature, not separate boundaries. Values are delivered to the member's own device so the agent's tools can use them; anything running in the agent (shells, plugins) can read its process.env, and the member controls the device that receives them. A desktop-only credential or hiding the broker endpoint wouldn't change what reaches that device. What is enforced: values never pass through an agent's Den calls, are never shown in any UI (admin-set ones), go only to the members they're assigned to, every change is audited, and the whole feature is off by default. These need a maintainer's decision.

This branch was successfully deployed

7 active deployments
Evidence / PR 6403 — efd551ae Deployed Oct 23, 2026 by github-actions[bot]
Preview – openwork-app — efd551ae Deployed Oct 23, 2026 by vercel[bot]
Preview – openwork-landing — efd551ae Deployed Oct 23, 2026 by vercel[bot]
Preview – openwork-den — efd551ae Deployed Oct 23, 2026 by vercel[bot]
Preview – openwork-diagnostics — efd551ae Deployed Oct 23, 2026 by vercel[bot]
staging - packages/docs — efd551ae Deployed Oct 23, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant