filecoin-project / filecoin-project/filecoin-pin

feat(auth): OS keychain storage via @napi-rs/keyring

Open
#680 0 comments 0 reactions 0 assignees View on GitHub
enhancement team/filecoin-pin team/fs-wg
Dominant language
TypeScript
Stars
26
Forks
21
Avg merge
5d 18h
Merged PRs (30d)
27

Description

Part of #457.

### Description

Store the keystore passphrase (not the raw key) in the OS-native vault: macOS Keychain, Windows Credential Manager, libsecret on Linux, via [`@napi-rs/keyring`](https://github.com/Brooooooklyn/keyring-node) (maintained napi-rs binding to the Rust `keyring` crate). After a one-time `wallet import`, the CLI unlocks the keystore without prompting, with access control enforced by the OS.

Depends on the keystore v3 child of #457; this tier sits on top of it, not beside it. Two wins: convenience for CLI users (no passphrase prompt, no passphrase env var), and headless unlock for local MCP servers spawned by AI assistants, which have no terminal to prompt on; for that shape keychain is the difference between working and not. It is not a security boundary against same-user local compromise, since an attacker with keychain access typically has the keystore file too.

### Scope

- `--keychain` opt-in flag on `keystore create|import` to save the passphrase; automatic lookup on use.
- Generated passphrases, so the user never knows or keeps a password: `keystore create --keychain` generates a random passphrase, stores it only in the OS vault, and never displays it. This requires a recovery path (`keystore export` re-encrypts to a user-supplied passphrase) and a plain warning that losing the keychain entry without an export makes the keystore unrecoverable.
- Session keys in the vault for agent callers: an agent that invokes filecoin-pin should be able to use a stored session key without the key ever entering the agent's environment, prompt context, or logs; filecoin-pin reads it from the vault itself. Document the honest boundary: OS keychains are same-user readable, so this prevents accidental exposure (transcripts, env dumps, error reports), not exfiltration by a compromised agent process. Containment for that case stays with the upload-only permission profile, expiry, and revocation (#682).
- Credential naming convention: service `filecoin-pin`, account `keystore:`, so multiple keystores and multiple OS users coexist.
- Skip keychain lookup entirely when `CI` is set: macOS runners can raise an invisible blocking keychain prompt that hangs the job instead of failing fast.
- Headless unlock is scoped to session-key material only. A headless process must never silently decrypt the owner keystore: an assistant-spawned MCP tool that can unlock the owner key without a TTY hands wallet-draining authority to anything that prompt-injects the agent. Owner-key decryption always requires an interactive confirmation; agents get session keys.
- Graceful fallback to the passphrase prompt when the platform vault is unavailable (headless Linux without libsecret, containers).
- Keep it out of browser exports; Node CLI only.
- Before adopting, review `@napi-rs/keyring`'s maintenance health (bus factor, release cadence, security contact); it is another native dependency near key material, and #457 documents why an unmaintained one is disqualifying.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.