Security
What it protects against. And what it doesn't.
"Covered" means a real barrier. "Limited" means the barrier is real but a determined attacker in that position gets past it. "Not covered" means keyward makes no promise. Read this before you trust the tool, and tell us where it's wrong.
Threat model
Standard primitives only: Argon2id, XChaCha20-Poly1305, HKDF-SHA256, Ed25519 and FIDO2 via RustCrypto and the platform's own WebAuthn or libfido2. The format is keyward's; the cryptography is not.
| Attacker | What they can do | Covered by | Status |
|---|---|---|---|
| Someone with the disk, the vault file, a backup or a partition image | Offline guessing against the passphrase slot | Argon2id (256 MiB, 3 passes) per guess; a FIDO2 slot needs the physical key and, with a PIN, the key locks after 8 tries; recovery slots are 256-bit secrets | Covered |
| The same, changing the file | Swap slots, KDF parameters or entries | Header and payload are one authenticated message (header as associated data); any change refuses to open | Covered |
| The same, with an old copy | Use a removed slot's credential against an old header to unwrap the data key | keyward rekey makes a new data key, keeps only the slot you authenticate with plus the phrase slot, and scrubs the previous copy. Slot removal alone is housekeeping; run rekey after removing a slot you no longer trust. Backups made before the rekey still open with the old credential | Covered after rekey |
| Other users on the machine | Reach the agent or service | Agent socket in a 0700 directory with a peer-uid check (Linux) or a pipe DACL for the user and SYSTEM only (Windows); the service checks the uid or pipe ACL and the calling program's path | Covered |
| A program running as you that merely shouldn't have keys | Ask the agent for identities or signatures | Caller identification (program path via /proc/<pid>/exe or the pipe client's image name) against a global and per-key allowlist | Covered for honest programs |
| Malware running as you | Call itself ssh | A name pattern only counts for a program in a directory you can't write (root-owned, Program Files); anything in your home, a download or /tmp is refused by name and keyward status says why. Full-path patterns vouch for a program wherever it is. Signature pinning of callers is planned; library preloading, DLL injection into a real ssh, or tracing it are not detected | Limited |
| Malware running as you | Read private keys or the data key out of a keyward process | Keys live in the service (SYSTEM/root) when the vault is behind it, handed out only as signatures to the one agent process that unlocked them (token, PID and program path). The agent holds public facts. Every keyward process is non-dumpable (Linux) or carries a DACL that denies same-user memory access and thread injection (Windows). Held keys are shielded under a 16 KiB locked prekey and decrypted only while signing; the Linux service locks its memory | Covered |
| Malware running as you | Use an allowed program to request signatures while the agent is unlocked | Policy: root and sudo targets re-authenticate every time, hardware keys need a touch, always and session keys prompt. Keys set to relaxed sign silently for non-root targets; non-login signatures (git signing) follow the key's setting | Limited: what a relaxed key reaches, malware reaches |
| Malware running as you | Ask the FIDO2 device for the vault's secret itself (the credential id and PRF input are in the plaintext header) and wait for you to touch | Nothing beyond you noticing an unexpected touch prompt. A touch answers whoever asked. The PIN stops a stolen key from being used, not a live phish. Unlike a logged passphrase the result can't be replayed later, and the attacker also needs the ciphertext | Limited |
| Malware running as you | Log a typed passphrase and copy the ciphertext | The passphrase is typed into keyward's own processes, but a same-user keylogger sees it. A vault file in your home is copyable by anything. Behind the service the ciphertext isn't a file to copy, but the installed keyward program can be driven by other code running as you (LD_PRELOAD, scripted input and the like), so the service protects the ciphertext from casual copying, not from determined same-user malware. Use a security-key slot and remove the passphrase slot to make the passphrase path go away | Limited |
| A server you log in to with agent forwarding | Ask your agent for signatures while you're connected | The agent sees forwarded in the verified session binding; forwarded requests always require re-authentication, and the prompt says where the request came from. keyward host never forwards | Covered |
| A server pretending to be another | Make the agent believe a signature is for a harmless account | Session binding is verified against the server's host-key signature over the session id; the host-bound login carries the host key the server itself checks. A forged destination yields a signature no real server accepts | Covered |
| A leaked management key | Talk to keyward-host | Only the fixed JSON vocabulary, through sudo to one binary. That vocabulary includes adding a key to any account, root included, so a management key is root on that server. It never touches disk unencrypted and only keyward host may use it | Covered for the transport; the key is root-equivalent |
| A user on a managed server | Trick keyward-host (root) via symlinks or crafted authorized_keys | Edits run with the user's own uid and gid, refuse symlinked .ssh or files, create files with O_NOFOLLOW|O_EXCL, and parse options structurally | Covered |
| Administrator or root on your machine | Read any process's memory, the service's keys, the hibernation file | Nothing. Root is root | Not covered |
| The kernel, firmware, a DMA device, a cold-boot attacker | Everything above | Nothing | Not covered |
| Someone shoulder-surfing or filming | The passphrase or the 24-word phrase | Nothing | Not covered |
| Quantum computers | Break Ed25519 | Session key exchange is already post-quantum in current OpenSSH. Login keys stay Ed25519 until OpenSSH ships PQ signatures; the entry format is algorithm-tagged so they can be added | Deferred |
Not covered, in one list
- Root or administrator on your machine.
- The kernel, firmware and hardware.
- A security-key touch given to the wrong asker.
- A passphrase typed while a keylogger runs.
- A
relaxedkey used by same-user malware. - A removed slot's old credential against an old copy of the vault, until you
rekey. - Stolen hardware keys with a known PIN.
- Anything you approve in a prompt that lies about what it is.
Being built
Short-lived certificates issued at approval, so a stolen key or vault is worthless within minutes. Code-signature checks on the program asking for a key. An external review before 1.0, with the report published. None of it is shipped yet; this page changes when it is.
Already built, and checked when you audit a server (keyward host report), not the moment it happens: canary keys, decoy key files whose use is reported as canary tripped; configuration drift, such as root login or password authentication re-enabled since the last audit; and logins the server accepted with your keys that keyward never signed.
Reporting a vulnerability
Found something? Email security@keyward.dafyddjon.es with what you found and how to reproduce it. You'll get a reply within a few days, credit if you want it, and a fix before any public write-up. Please don't test against servers you don't own.