Skip to content

feat(store): fetch secrets with bws and bw - #50

Merged
groupsky merged 1 commit into
mainfrom
feat/store
Oct 14, 2026
Merged

groupsky merged 1 commit into
mainfrom
feat/store

Conversation

@groupsky

Copy link
Copy Markdown
Contributor

What

internal/store fetches a secret after an approval, by running Bitwarden's own command-line programs. nodkey does not link the Bitwarden SDK.

  • bws (Bitwarden Secrets Manager): bws secret get <id> --output json --color no. The access token is only in BWS_ACCESS_TOKEN, never in the arguments. Only value is read, and the answer's id must be the asked one.
  • bw (Bitwarden Password Manager, with a separate account): unlock at start with --passwordfile (the password never passes through nodkey), keep the session key in memory and pass it only as BW_SESSION, bw sync --force before each fetch, bw get item. Only login.password is read; an item in the trash or archived is refused. If bw is logged out, deny; if it is locked, unlock again on the next request.
  • Running the programs: by absolute path, without a shell, with only HOME, a fixed PATH (for bw) and the one secret variable, a timeout, capped output, stdout never logged, stderr never read, and the whole process group killed after each run. A program dies with the broker. Each store has its own private home (0700).
  • Checks: clean absolute paths, safe PATH directories, no bw-data directory next to bw or node, the password file's size and type.
  • Values: a Value type that hides itself in every print and log form, and can be cleared. A strict JSON reader refuses repeated keys, keys in another case, invalid UTF-8 and NUL bytes.

Docs

  • DESIGN.md sections 5, 11, 14, 16 (a new "Store programs" table: each command and the fields read) and 17.
  • THREAT-MODEL.md: section 2, T18, T26, and the new T29.

Review

Three rounds with the security-reviewer agent; the last said "ready to commit". The CLI behaviour comes from reading the source of bws 2.1.0 and bw 2026.9.1; neither program was run.

Fixed on the way:

  • bw sync --force: without it, bw trusts the broker's clock and could keep handing out an item that was moved to the trash;
  • bw gets a narrow fixed PATH; each directory and each node in it get the same check as a store program (config.CheckProgram, now exported);
  • a bw-data directory next to bw or node is refused (bw would keep its state there, outside the private home);
  • clean absolute paths for programs and files; the answer's id must match; NUL bytes and archived items are refused; the password file's size is checked;
  • a store program dies with the broker.

Left for later issues: #11 (the broker sets its own core-dump limit, checks files before New, fetches only after the decision is on disk), #16 (install, login and the example unit).

Closes #8

Run Bitwarden's own programs by absolute path, with a minimal environment, a timeout and capped output; read only the needed field; never log a value.

Closes #8
@groupsky groupsky added this to the v1 milestone Oct 14, 2026
@groupsky
groupsky merged commit 03bb431 into main Oct 14, 2026
6 checks passed
@groupsky
groupsky deleted the feat/store branch October 14, 2026 21:14
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.

Secret stores: bws and bw

1 participant