Skip to content

feat: organization-key (Collections) support + TUI reveal from any pane#47

Merged
UnbreakableMJ merged 1 commit into
mainfrom
org-key-support
Jun 22, 2026
Merged

feat: organization-key (Collections) support + TUI reveal from any pane#47
UnbreakableMJ merged 1 commit into
mainfrom
org-key-support

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

Two fixes from daily-driving Vault against a Bitwarden-cloud account whose vault is ~99% organization/Collection-owned (2262 of 2274 items).

Organization-key support (the headline)

Vault decrypted only personal ciphers (and per-cipher keys under the user key); organization items were skipped — their fields are encrypted under an org key Vault didn't hold. Now, at unlock, the agent:

  1. recovers the account RSA private key from /sync profile.privateKey (a type-2 EncString under the user key);
  2. RSA-OAEP-SHA1-unwraps each profile.organizations[].key (type-4 EncString) into that org's symmetric key;
  3. routes every cipher's decryption by organization_id — org key vs user key — via Vault::base_keys.

Works online and from the offline cache (the cached /sync carries the profile). New vault_core::org_key module and a new rsa dependency (ring has no RSA decryption), with a justified RUSTSEC-2023-0071 ignore in deny.toml + CI (the Marvin timing attack needs a network decryption oracle; Vault unwraps org keys once, locally, at unlock).

Scope: items whose org key can't be unwrapped are still skipped (logged); editing org items is refused for now — the write path would re-encrypt under the wrong key (reads/copy work). Org-aware writes are a follow-up.

TUI Space reveals from any pane

Space revealed a login's password from the item list but did nothing in the detail pane (logins have no per-field rows) or the folder pane. Resolution moved into a testable App::reveal_target: cards/identities reveal the cursor-selected masked field in the detail pane; logins/notes fall back to the primary secret; the list and folder panes reveal the selected item's primary secret — so Space works from all three panes.

Verification

Full just ci green (fmt, clippy -D warnings, test, deny, audit, reuse). New tests: RSA OAEP round-trip, org-cipher decrypt + edit-refusal, reveal_target across panes/types. Live-verified against the real cloud vault: login (password + TOTP), all 2274 items decrypt, org item reveal/copy, and Space from all three TUI panes.

🤖 Generated with Claude Code

…ny pane

Two fixes from daily-driving Vault against a Bitwarden-cloud account whose
vault is almost entirely organization/Collection-owned.

Organization-key support (the bulk of the change):
- Vault decrypted only personal ciphers (and per-cipher keys under the user
  key); organization items — ~99% of a Collections-heavy vault — were skipped,
  their fields being encrypted under an org key Vault didn't hold. At unlock the
  agent now recovers the account RSA private key from `profile.privateKey`,
  RSA-OAEP-SHA1-unwraps each `profile.organizations[].key` into that org's
  symmetric key, and routes every cipher's decryption by `organization_id`
  (org key vs user key). Works online and from the offline cache. New
  `vault_core::org_key` module + `rsa` dependency (`ring` has no RSA
  decryption); justified RUSTSEC-2023-0071 ignore in deny.toml / CI. Items whose
  org key can't be unwrapped are still skipped; editing org items is refused for
  now (the write path would re-encrypt under the wrong key).

TUI Space-to-reveal:
- `Space` revealed a login's password from the item list but did nothing in the
  detail pane (logins have no per-field rows) or the folder pane. Target
  resolution moved into a testable `App::reveal_target`, so `Space` reveals from
  all three panes; cards/identities still reveal the cursor-selected masked
  field in the detail pane.

Tests: RSA round-trip, org-cipher decrypt + edit-refusal, reveal_target across
panes/types. Full `just ci` green; verified live (2274 items decrypt).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@UnbreakableMJ UnbreakableMJ merged commit 112db8a into main Jun 22, 2026
9 checks passed
@UnbreakableMJ UnbreakableMJ deleted the org-key-support branch June 22, 2026 22:54
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