Skip to content

fix: client zip bundles another client's private keys when one name prefixes another #43

Description

@catinspace-au

generate-client bundles one client's zip with a prefix glob, so a client whose name is a prefix of another client's name packages that other client's private keys.

_bundle_client_zip (scripts/generate-client.py) globs {client_name}-*. Client names allow - (validate_client_name permits [a-zA-Z0-9_-]+), so hyperi matches every file belonging to hyperi-laptop.

Proved it:

hyperi.zip would contain: ['hyperi-laptop-udp-split.ovpn', 'hyperi-laptop-wg-split.conf', 'hyperi-udp-split.ovpn', 'hyperi-wg-split.conf']

The .ovpn files carry the embedded client key and the tls-crypt-v2 key. The .conf files carry the WireGuard private key. So whoever gets hyperi.zip gets hyperi-laptop's full credentials, and the docstring on that function says the per-client bundling exists precisely so "one client's private keys are never packaged alongside another's".

It only runs one way -- the SHORTER name swallows the longer one, never the reverse.

Same glob class bites revocation. revoke_client globs {client_name}-*.ovpn, so revoking hyperi deletes hyperi-laptop's .ovpn files out of the output dir without revoking that client's certificate. Less serious (the cert stays valid, the files regenerate) but it is the same mistake. The WireGuard removal glob {client_name}-wg*.conf is safe, because the literal -wg anchors it.

Nothing on devex hits this today -- the client names there are hyperi and devex-hyperi-io, and hyperi-* does not match devex-hyperi-io-*. It is latent, not live. But "do not name a client a prefix of another client" is not a rule anyone knows about, and the failure is silent.

The fix is to match on the actual filename boundary rather than a bare prefix, on both globs.

Done when a client named foo and a client named foo-bar can coexist, and foo.zip contains only foo's files.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions