Security Best Practices for Handling Mnemonics in the Osmosis Agent Toolkit

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 (lines 28‑31), the code explicitly prioritizes the environment variable to keep secrets out of shell history:

// 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 (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, 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 (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, 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:

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 (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 (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 stores the mnemonic only in memory during the brief window needed to derive the seed, and the OsmosisAgentServer in 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →