Skip to content

Server 2.0.0-alpha.5: security fix, a signature with every wrapped vault key - #14

Merged
usermaneGermane merged 1 commit into
mainfrom
v3-signed-keys
Nov 12, 2026
Merged

usermaneGermane merged 1 commit into
mainfrom
v3-signed-keys

Conversation

@usermaneGermane

Copy link
Copy Markdown
Owner

Security fix, server side. Server version 2.0.0-alpha.5 (a test version; Latest stays as it is). Affects the SecretSpace 3 test versions only; the 2.x routes and the stable releases are not involved.

The problem

The server stores each member's wrapped copy of a vault key. Until now a device took whatever copy the server listed. A dishonest server, or someone who broke into it, could therefore wrap a key of its own to a member's public key, call it a new key generation, and read the vault the device uploaded under it at its next sync. A test reproduced this and read a stored password.

The fix (most of it is in the clients)

  • The account that wraps a key now signs it: which vault, which key generation, for whom, and the wrapped key itself. The clients check that signature before they take a key.
  • The server's part is to keep the signature with the key and return it:
    • key_sig in POST /v2/vaults and in PUT /v2/vaults/<id>/members/<user> for a new member;
    • key_sigs, one per member who stays, in POST /v2/vaults/<id>/rotate;
    • key_sig and key_signer with each vault in /v2/me.
  • key_signer is always the account whose session sent the key, never a name from the request.
  • PUT /v2/vaults/<id>/key-sig: a member signs the key it already holds, for vaults made before this version. Only while that key has no signature.
  • A key change without signatures clears the old ones, so a signature never sits beside a key it was not made for.
  • /health lists "signed-keys".

The server does not verify these signatures: it has no key to verify with, and its being untrusted is the point.

Tests

  • New tests/test_server_v2_key_sigs.py: 25 tests over real HTTP.
  • 8 deliberately broken guards, all caught.
  • Full suite green locally.

server/passman_server.py is the same file in SecretSpace-Server-Linux and SecretSpace-Server-Windows.

🤖 Generated with Claude Code

https://claude.ai/code/session_011ojnyVg7ccsR3pZ64s7aRH

Security fix (SecretSpace 3 test versions only). The server stores each
member's wrapped copy of a vault key; a device took whatever copy was
listed, so a dishonest server could wrap a key of its own, call it a new
key generation, and read the vault uploaded under it.

The clients now sign each wrapped key and check the signature before they
take one. The server keeps the signature with the key and returns it:

- key_sig in POST /v2/vaults and in PUT .../members/<user> (new member),
  key_sigs in POST .../rotate (one per member who stays; a key change
  without them clears the old ones);
- key_sig and key_signer with each vault in /v2/me; key_signer is the
  account whose session sent the key, never a name from the request;
- PUT /v2/vaults/<id>/key-sig: a member signs the key it already holds
  (vaults from before this version), only while it has no signature;
- /health lists "signed-keys".

The server does not verify the signatures; the devices do.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ojnyVg7ccsR3pZ64s7aRH
@usermaneGermane
usermaneGermane merged commit 493b69f into main Nov 12, 2026
3 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