Skip to content

wallet-cli: Branded Password / Srp opaque types #8778

@sirtimid

Description

@sirtimid

Surfaced as a deferred follow-up from PR #8446.

Problem

`DaemonSpawnConfig.password` and `DaemonSpawnConfig.srp` are typed as plain `string`. They flow through several layers:

  • oclif flag parsing in `packages/wallet-cli/src/commands/daemon/start.ts`
  • `MM_WALLET_PASSWORD` / `MM_WALLET_SRP` env-var reads in `packages/wallet-cli/src/daemon/daemon-entry.ts`
  • `createWallet` config in `packages/wallet-cli/src/daemon/wallet-factory.ts`
  • `importSecretRecoveryPhrase` in `@metamask/wallet`

At every hop the value is a `string` with no friction against accidental logging, JSON serialization, or display. The next "log the spawn config for debugging" PR is one line away from leaking the SRP into `daemon.log`.

Proposed direction

Introduce opaque branded types in `packages/wallet-cli/src/daemon/types.ts` (or a new `secrets.ts`):

```ts
declare const PasswordBrand: unique symbol;
export type Password = string & { readonly [PasswordBrand]: true };
export function asPassword(value: string): Password { /* validate non-empty */ }

declare const SrpBrand: unique symbol;
export type Srp = string & { readonly [SrpBrand]: true };
export function asSrp(value: string): Srp { /* validate BIP-39 word count */ }
```

Optionally wrap each in a small class with a redacting `toString` / `util.inspect.custom` so accidental `console.log`/`JSON.stringify` prints `'[redacted]'` instead of the value. `importSecretRecoveryPhrase` in `@metamask/wallet` may need its signature updated to accept the branded types (or stay on `string` and let the CLI `unwrap()` at the boundary).

Acceptance

  • `DaemonSpawnConfig`, `start.ts` flags, env-var reads, `createWallet` config, and any other call sites use `Password`/`Srp` instead of `string`.
  • A unit test demonstrates that a `util.inspect` of a value typed as `Password` does not leak the underlying string.
  • No new prod logger paths can compile while passing a `Password`/`Srp` directly.

Context

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions