1 pointby kcmastrpc7 hours ago1 comment
  • kcmastrpc7 hours ago
    Author here. Short version: if your agent needs secrets, the common routes are (1) dump them in its env, (2) materialize a .env file, or (3) give it a shell and let it run bws itself. All three have the same problem: the blast radius is everything the token can touch, and prompt injection turns them into full RCE and sadness.

    This wraps the bws CLI as an MCP server with explicit CRUD tools for projects and secrets, plus a bws_run that takes an argv array instead of a shell string. First draft of bws_run accepted "sh -c ..."; that's the eval surface I wanted to remove. Shipped version forces explicit program invocation, and if you genuinely want a shell pipeline you have to put sh as argv[0], which is both visible in audit logs and trivially noticed.

    A few things I thought worth calling out:

    - Destructive tools (*_delete, bws_run) require confirm: true. Not a safety net (the model will set it); a hook point for your approval tooling so you don't have to pattern-match argument shapes.

    - Wraps the CLI, not the Rust SDK. Subprocess + JSON parse is 350 lines. SDK path would have been weeks.

    - No mocks in the test suite. Three of four integration tests failed against the real bws binary on first run. Caught a bws secret delete returns-plain-text bug that the JSON-stub protocol tests missed.

    Code: https://github.com/kvncrw/bws-mcp-server (GPL-3.0). Issues and PRs welcome, especially from anyone running Vaultwarden with Secrets Manager — I don't have one to test against.