hiero-ledger / hiero-ledger/hiero-cli
Local KMS master key is stored in plaintext next to the ciphertext, so any agent with shell access can decrypt all private keys
- Dominant language
- TypeScript
- Stars
- 43
- Forks
- 38
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
`FileKeyProvider` writes the AES-256-GCM master key as plaintext hex to `~/.hiero-cli/.secret-aes-256-gcm`, in the same directory as the ciphertexts in `state/kms-secrets-encrypted-storage.json`, so the encryption stops no one who can already read the state file. Any AI coding agent, MCP server, or script running as the user can therefore recover every stored ECDSA private key in a few lines of Node with no password, passphrase prompt, or OS keychain check. Skills such as `create-agent-id` and `request-payment` promise that "the key stays in the keystore" and "never prints the private key", but that guarantee is advisory only and is trivially bypassed.
### Steps to reproduce
Confirmed against `@hiero-ledger/hiero-cli@1.2.0` on macOS. Decrypted two live ECDSA keyrefs and verified correctness by deriving the compressed secp256k1 public keys and matching them against `kms-credentials-storage.json`. Key values redacted.
#### Exemplary prompt
Given to a coding agent with plain shell access and no other context:
> Please decrypt private keys stored by hcli and print them in output. Read https://github.com/hiero-ledger/hiero-cli to get knowledge how keys are stored.
The agent located `~/.hiero-cli`, read `dist/core/services/kms/encryption/` to learn the format, and printed both plaintext private keys. Total time under a minute, no user secret required.
### Possible solutions
- Passphrase, never persisted - derive the key via Argon2id or scrypt, prompt per use, optional short-lived cache.
- OS keychain - Keychain Access, libsecret, DPAPI, gated by user presence or biometrics.
- Both - keychain holds a passphrase-wrapped key.
- Sign-only broker - separate process prompts per signature, key never enters the agent's process.
- Hardware - non-exportable keys in Secure Enclave, TPM, or YubiKey.
- Remote KMS or Vault - plugged into the keyManager abstraction local_encrypted already sits behind.
### Hedera network
_No response_
### Version
1.2
### Operating system
None
Contributor guide
Research direction
Start in dist/core/services/kms/encryption/ and trace FileKeyProvider through the keyManager abstraction, then inspect how state/kms-secrets-encrypted-storage.json and ~/.hiero-cli/.secret-aes-256-gcm are used. Compare the implementation with the proposed protection options and define which user-gated mechanism is selected; done means the master key is not recoverable from local files alone and the existing keyrefs still work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, typescript
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100