Skip to content

[PM-35788] fix: fail fast with clear error when vault is locked or unauthenticated#182

Open
tecnologicachile wants to merge 6 commits into
bitwarden:mainfrom
tecnologicachile:fix/fail-fast-when-vault-locked
Open

[PM-35788] fix: fail fast with clear error when vault is locked or unauthenticated#182
tecnologicachile wants to merge 6 commits into
bitwarden:mainfrom
tecnologicachile:fix/fail-fast-when-vault-locked

Conversation

@tecnologicachile
Copy link
Copy Markdown
Contributor

Summary

When the vault is locked or the user is not authenticated, CLI tools like list, get, create_item, etc. call bw directly. The CLI either times out or returns a generic stderr message that is hard for an LLM — or a human — to interpret and act on.

This PR adds a pre-flight vault status check to every CLI tool that requires an unlocked vault.

Changes

src/utils/cli.ts — new exported function ensureVaultUnlocked():

  • Calls bw status (always fast, works regardless of vault state)
  • Returns a clear, actionable error message when locked or unauthenticated
  • Returns null (safe to proceed) when unlocked
  • Falls back to null on unexpected output so no existing behaviour regresses

src/index.ts — vault guard in the tool dispatcher:

  • VAULT_REQUIRED_CLI_TOOLS set lists every CLI tool that needs the vault
  • Before executing any of those tools, calls ensureVaultUnlocked()
  • Returns a structured MCP error immediately if the vault is not ready
  • Excluded from the check: status, lock, generate (work without vault) and all org_* tools (use the Bitwarden REST API with their own OAuth2 credentials, not the local CLI session)

Error messages

Vault state Message
locked Vault is locked. Call the "unlock" tool with your master password to unlock it, then retry.
unauthenticated Not logged in to Bitwarden. Use "bw login" to authenticate first, then retry.

Test plan

  • With vault locked: calling list, get, or any other vault-required tool returns the locked error immediately without waiting for bw to time out
  • With vault unlocked: all tools continue to work as before
  • status, lock, and generate are unaffected (no pre-flight check)
  • All org API tools are unaffected (they use REST API, not the local vault)
  • Build passes: npm run build
  • Tests pass (excluding cli-commands.spec.ts which makes real bw calls and was already failing before this PR): npm test

🤖 Generated with Claude Code

@tecnologicachile tecnologicachile requested a review from a team as a code owner April 24, 2026 03:07
@bitwarden-bot
Copy link
Copy Markdown

Thank you for your contribution! We've added this to our internal tracking system for review.
ID: PM-35788
Link: https://bitwarden.atlassian.net/browse/PM-35788

Details on our contribution process can be found here: https://contributing.bitwarden.com/contributing/pull-requests/community-pr-process.

@bitwarden-bot bitwarden-bot changed the title [PM-XXXXX] fix: fail fast with clear error when vault is locked or unauthenticated [PM-35788] [PM-XXXXX] fix: fail fast with clear error when vault is locked or unauthenticated Apr 24, 2026
The `create_item` and `edit_item` tools currently expose only name, type,
login/card/identity/secureNote and folderId. This forces MCP consumers to
drop down to the `bw` CLI directly whenever they need to:

  - Create or update a vault item with custom fields
  - Put an item inside an organization + collection
  - Rename or migrate a custom field on an existing item

The underlying `bw` CLI already understands all three (fields are part of
the item JSON; organizationId/collectionIds live in the same object; the
CLI also needs --organizationid as a flag at create time), so this PR just
surfaces them through the MCP schema and threads them through the handler.

Changes
-------
- src/utils/types.ts: extend BitwardenItem with fields, organizationId,
  collectionIds.
- src/schemas/cli.ts: new customFieldSchema (name + optional value + type
  0..3) and extensions to createItemSchema/editItemSchema.
- src/handlers/cli.ts:
  * handleCreateItem copies organizationId/collectionIds/fields into the
    JSON item and appends `--organizationid <id>` when present.
  * handleEditItem updates organizationId/collectionIds and replaces the
    fields array on the existing item when one is supplied (callers that
    want to merge should read the item first and merge client-side).
- src/tools/cli.ts: exposes the new parameters to MCP clients for both
  create_item and edit_item.

Backward compatible: all new parameters are optional and existing calls
behave identically when they're omitted.
Tools that require an unlocked vault (list, get, create_item, edit_item,
delete, and others) currently call `bw` directly. When the vault is locked
or the user is not authenticated, the CLI either times out waiting for a
response or returns a generic stderr message that is difficult for an LLM
to interpret and act on.

This commit adds a pre-flight vault status check to every CLI tool that
requires an unlocked vault:

 • A new `ensureVaultUnlocked()` utility function in `src/utils/cli.ts`
   calls `bw status` (which always responds immediately regardless of vault
   state) and parses the `status` field.
 • When the vault is **locked**, it returns a structured error:
   "Vault is locked. Call the 'unlock' tool with your master password to
   unlock it, then retry."
 • When the session is **unauthenticated**, it returns:
   "Not logged in to Bitwarden. Use 'bw login' to authenticate first,
   then retry."
 • If status cannot be determined (unexpected output, JSON parse error),
   it returns `null` and the actual command runs as before — no regression
   in error handling.

The guard in `src/index.ts` is applied through a `VAULT_REQUIRED_CLI_TOOLS`
set. Excluded from the check:
 • `status`, `lock`, `generate` — work without an unlocked vault.
 • All `org_*` tools — use the Bitwarden REST API with their own OAuth2
   credentials, not the local CLI vault session.
The ensureVaultUnlocked() guard returns an error message telling the LLM
to call the 'unlock' tool, but that tool did not exist. This adds it:

- unlockSchema: requires a master password (passed via env var, never as
  a shell argument, to avoid exposure in the process list)
- unlockTool: exposed to the LLM with clear description
- handleUnlock: calls 'bw unlock --passwordenv ... --raw', then updates
  process.env.BW_SESSION so subsequent CLI tools work without restart
- executeCliCommand: accepts optional extraEnv to pass extra variables
  to the spawned process
- security allowlist: adds 'unlock' as a valid Bitwarden command
bw CLI often emits Node.js deprecation warnings to stderr on a successful
unlock, causing errorOutput to be set. The previous check
`response.output && !response.errorOutput` would then skip saving the
session key, leaving the vault effectively locked for subsequent calls.

Use the presence of output (the raw session key) as the sole success
signal instead.
- Success: "Vault unlocked successfully. You can now retry the operation."
- Failure: actionable message telling the LLM to ask the user to confirm
  the password and retry, instead of exposing a raw bw CLI error
- Tool description: clarifies that the session persists automatically on
  success and what to do on failure
Adopts upstream's native OS dialog flow (src/utils/unlock.ts) for
environments with a graphical interface, while keeping the password
parameter path for headless/server environments:

- No password provided → native OS dialog (osascript / zenity / kdialog)
  The master password never reaches the LLM or MCP protocol.
- Password provided → headless path via --passwordenv (existing behavior)
  For servers and LXC containers without a display.

If the GUI dialog fails because the environment is headless, the LLM
receives a clear message instructing it to retry with the password
parameter instead.
@tecnologicachile tecnologicachile force-pushed the fix/fail-fast-when-vault-locked branch from 63c3f5c to 987a707 Compare April 25, 2026 03:35
@withinfocus withinfocus changed the title [PM-35788] [PM-XXXXX] fix: fail fast with clear error when vault is locked or unauthenticated [PM-35788] fix: fail fast with clear error when vault is locked or unauthenticated May 6, 2026
@withinfocus
Copy link
Copy Markdown
Contributor

@tecnologicachile take a look at what just merged in and give it a try -- there's a whole new unlock flow now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants