# Security Best Practices for Handling Mnemonics in the Osmosis Agent Toolkit

> Learn secure mnemonic handling best practices for the Osmosis Agent Toolkit. Store mnemonics in env vars, avoid logging, and validate with @scure/bip39 for robust security.

- Repository: [Jon Ator/osmosis-agent-toolkit](https://github.com/jonator/osmosis-agent-toolkit)
- Tags: best-practices
- Published: 2026-03-05

---

**Store mnemonics exclusively in environment variables like `OSMOSIS_MNEMONIC`, never log them, and validate them with `@scure/bip39` before passing to the `OsmosisAgentToolkit` constructor.**

The `jonator/osmosis-agent-toolkit` repository treats the **mnemonic** (BIP-39 seed phrase) as the single source of cryptographic authority for signing Osmosis transactions. Because anyone with the mnemonic can fully recover the wallet and drain its funds, following security best practices for handling mnemonics is critical when deploying this toolkit in production environments.

## How the Toolkit Handles Mnemonic Injection

The Osmosis Agent Toolkit centralizes mnemonic handling to minimize exposure surfaces. Understanding these internal patterns helps you align your deployment practices with the library’s security model.

### Environment Variable and CLI Argument Parsing

The MCP server entry point accepts mnemonics through two channels: a `--mnemonic` CLI flag and the `OSMOSIS_MNEMONIC` environment variable. In [`packages/mcp/src/index.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/index.ts) (lines 28‑31), the code explicitly prioritizes the environment variable to keep secrets out of shell history:

```typescript
// packages/mcp/src/index.ts
const mnemonic = options.mnemonic || process.env.OSMOSIS_MNEMONIC;
if (!mnemonic) {
  throw new Error('Osmosis mnemonic not provided. Please either pass it as an argument --mnemonic=$MNEMONIC or set the OSMOSIS_MNEMONIC environment variable.');
}

```

### Centralized Account Construction

The `OsmosisAgentToolkit` class in [`packages/core/src/toolkit.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/toolkit.ts) (lines 35‑36) constructs a single `Account` instance from the mnemonic during initialization. This ensures the seed phrase is processed exactly once—converted to a cryptographic seed via `mnemonicToSeedSync` from `@scure/bip39`—and then wrapped in a `DirectSecp256k1HdWallet` (see [`packages/core/src/account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/account.ts), lines 67‑146). By centralizing this logic, the toolkit prevents ad-hoc mnemonic handling throughout the application.

### Server-Side Isolation

In [`packages/mcp/src/server.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/server.ts) (lines 11‑17), the `OsmosisAgentServer` receives the mnemonic only at construction time and stores it exclusively in memory within the toolkit instance. The server never serializes the mnemonic to disk, logs it, or exposes it through API endpoints.

## Security Best Practices for Mnemonic Storage

When deploying the Osmosis Agent Toolkit, implement the following checklist to protect mnemonics from exposure:

- **Prefer environment variables over CLI flags.** Set `OSMOSIS_MNEMONIC` in a secure runtime environment such as Docker secrets, Kubernetes sealed secrets, or a CI/CD secret store. This prevents the mnemonic from appearing in shell history or process listings.

- **Avoid baking mnemonics into images.** Never hardcode the mnemonic in source code or Dockerfiles. Supply it at runtime via orchestration secrets.

- **Restrict file system permissions.** Run the MCP server as a non-root user with read-only access to the application code. This limits the blast radius if the container is compromised.

- **Never log the mnemonic.** Audit logging statements to ensure they do not interpolate the `mnemonic` variable. The toolkit’s error messages intentionally display only generic prompts (see [`packages/mcp/src/index.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/index.ts), lines 31‑33).

- **Validate mnemonic format before use.** Use `validateMnemonic` from `@scure/bip39` to ensure the string is a valid BIP-39 phrase before passing it to the toolkit constructor. This prevents runtime failures from malformed input.

- **Rotate mnemonics periodically.** Generate new wallets and transfer funds when operational security policies require rotation. This limits exposure time if a leak occurs.

- **Encrypt at rest if persisting.** If you must store the mnemonic on disk, encrypt it with a KMS-managed key and decrypt it only at runtime inside the application.

## Validating Mnemonics Before Initialization

Always validate the mnemonic using the same library the toolkit relies on. This catches typos or invalid word lists before the `OsmosisAgentToolkit` attempts to derive keys:

```typescript
import { validateMnemonic } from '@scure/bip39';

function loadMnemonic(raw: string): string {
  const trimmed = raw.trim();
  if (!validateMnemonic(trimmed)) {
    throw new Error('Invalid BIP-39 mnemonic supplied');
  }
  return trimmed;
}

// Usage in your server initialization
const mnemonic = loadMnemonic(process.env.OSMOSIS_MNEMONIC ?? '');
const server = new OsmosisAgentServer(mnemonic);

```

## Summary

- **Environment variables** (`OSMOSIS_MNEMONIC`) are the safest injection method, keeping secrets out of shell history and process monitors.
- **Centralized handling** in `OsmosisAgentToolkit` and `Account` ensures the mnemonic is processed once and never logged.
- **Validation** with `@scure/bip39` prevents runtime errors from malformed phrases.
- **Runtime isolation** via non-root containers and secret management systems minimizes exposure surfaces.

## Frequently Asked Questions

### Should I use the `--mnemonic` CLI flag or the `OSMOSIS_MNEMONIC` environment variable?

Prefer the `OSMOSIS_MNEMONIC` environment variable for production deployments. CLI flags appear in shell history and process listings (visible via `ps`), whereas environment variables can be injected securely via Docker secrets, Kubernetes sealed secrets, or CI/CD vaults. The toolkit checks the environment variable first in [`packages/mcp/src/index.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/index.ts) (lines 28‑31), making this the path of least resistance.

### How does the toolkit prevent the mnemonic from leaking into logs?

The `OsmosisAgentToolkit` never writes the mnemonic to stdout or log files. In [`packages/mcp/src/index.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/index.ts) (lines 31‑33), error messages regarding missing mnemonics display only generic instructions, never the value itself. The `Account` class in [`packages/core/src/account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/account.ts) stores the mnemonic only in memory during the brief window needed to derive the seed, and the `OsmosisAgentServer` in [`packages/mcp/src/server.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/mcp/src/server.ts) holds no direct reference to the string after construction.

### Is it safe to store the mnemonic in a Docker environment file?

Standard Docker `.env` files are plaintext and should be treated as insecure. Instead, use **Docker secrets** (swarm mode) or **Kubernetes secrets** mounted as files, then read the mnemonic from `/run/secrets/osmosis_mnemonic` into the `OSMOSIS_MNEMONIC` variable at runtime. This keeps the secret out of the image layers and the host environment file. If you must use an `.env` file temporarily, ensure it is excluded from version control via `.gitignore` and has restrictive file permissions (`chmod 600`).

### How do I validate that my mnemonic is correctly formatted before starting the server?

Use the `validateMnemonic` function from `@scure/bip39` (the same library the toolkit uses internally) to check the phrase before passing it to the `OsmosisAgentToolkit` constructor. This catches invalid word lists or checksum errors early. See the code example in the "Validating Mnemonics Before Initialization" section above, which demonstrates trimming whitespace and throwing a descriptive error if validation fails.