Skip to content

Let agents use vault logins and 2FA codes inside their VM (GODM-18) - #19

Merged
danielehrhardt merged 2 commits into
mainfrom
agent/c-pro/ff2339945342
Sep 29, 2026
Merged

danielehrhardt merged 2 commits into
mainfrom
agent/c-pro/ff2339945342

Conversation

@danielehrhardt

Copy link
Copy Markdown
Contributor

What does this change?

Agents working in a macOS VM can now sign in there with the vault's logins and 2FA codes (GODM-18).

  • New vm tools fill_login / fill_totp. Godmode types the username, password or current 2FA code key by key over VNC into the field the agent clicked on the VM's screen. The value never appears in a tool result, and both tools take an optional coordinate to click the field first.
  • Passwords only go into password fields. Before typing, Godmode checks that macOS secure keyboard input is on (ioreg → kCGSSessionSecureInputPID), and checks again afterwards. If focus moved while typing, the typed characters are erased again and the fill fails.
    • ioreg and ps run through tart exec without a shell, so the guest user's shell setup can't fake them.
    • Terminals with Secure Keyboard Entry are refused.
  • Nothing goes through the guest clipboard. Secrets that aren't plain ASCII are refused instead of pasted.
  • Opt-in. New setting vm.vaultFill is off by default. Turning it on needs the vault passphrase (grant), the same as other security-relevant switches. While it's off, the tools tell the agent where the human can turn it on.
  • Same scope and audit as browser fills. Scope checks reuse revealForAgent / codeForAgent / totpForAgent. Every attempt, including refusals and failures, goes into the audit log as credential.fill / totp.fill with the VM id and the app that owned the password field.
  • Prompt. The VM section explains the flow. Resumed turns restate whether VM fills are allowed.
  • Settings → Virtual machines gets a "Logins and 2FA codes" card. It is honest about the trade-off: unlike in the browser, a fill can't be bound to a website, and the agent controls the VM.

How was it tested?

  • pnpm typecheck for shared, core and desktop; pnpm --filter @godmode/desktop build.
  • bun test in packages/core after merging the latest main: 593 pass, 9 skip, 0 fail.
  • New tests in test/vms.test.ts against the fake tart, whose ioreg, ps and pbcopy shims simulate a focused password field. They cover:
    • typed keys and the Return for submit
    • no-password-field, terminal, focus-moved (typed characters erased) and non-ASCII refusals
    • scope refusals across workspaces
    • locked vault
    • audit entries with no secrets
    • the grant requirement on PUT /api/settings
    • the resumed-prompt text
  • Checked the secure-input detection on macOS 27: calling EnableSecureEventInput makes the PID appear in ioreg, and it disappears after DisableSecureEventInput.
  • Checked the settings UI in the web dashboard: toggle → passphrase prompt → setting saved (screenshots on GODM-18).
  • Not tested: a real Tart guest. The secure-input check inside a guest and typing into a secure field over Apple Screen Sharing haven't been tried on an actual VM.

Checklist

  • pnpm typecheck and pnpm test pass
  • cargo clippy / cargo test pass (if apps/desktop/src-tauri changed) — not changed
  • API changes are reflected in packages/shared and apps/desktop/src/lib/api.ts
  • No secrets, tokens or personal data in code, fixtures, logs or screenshots
  • Docs updated where behaviour changed (docs/ARCHITECTURE.md, README)

New vm tools fill_login / fill_totp type a saved login or the current
2FA code into the focused field on the VM's screen, key by key over VNC,
so the value never reaches the model. Passwords only go in while macOS
secure keyboard input is on (checked before and after typing, with
ioreg/ps run without a shell; terminals refused), secrets are never
pasted, and every attempt is audited.

Opt-in via Settings -> Virtual machines (vm.vaultFill, needs the vault
passphrase to turn on), since a fill in a VM can't be bound to a website.
@danielehrhardt
danielehrhardt merged commit 5ef318c into main Sep 29, 2026
5 checks passed
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