How SimStudio AI Sim Handles Secrets and Credential Management

SimStudio AI Sim implements a defense-in-depth strategy for secrets and credential management that exclusively uses environment variables for configuration, encrypts all persisted credentials with AES-256-GCM, and isolates authentication verification to prevent secret exposure in source code.

SimStudio AI Sim is an open-source AI workflow platform that processes sensitive API keys, database credentials, and authentication tokens. Understanding its approach to secrets and credential management is essential for developers deploying secure production instances. The codebase follows a strict layered security model that keeps sensitive data out of repositories while ensuring cryptographic protection for any credentials stored at rest.

Environment-Driven Secret Configuration

The foundation of SimStudio AI Sim's security model prohibits hard-coded secrets entirely. All sensitive configuration values—including database URLs, SSO credentials, feature flags, and encryption keys—are sourced exclusively from process.env at runtime.

In packages/db/index.ts, the database connection initializes using process.env.DATABASE_URL, ensuring connection strings remain outside version control. Similarly, SSO provider registration in packages/db/scripts/register-sso-provider.ts reads client IDs and secrets from environment variables prefixed with SSO_. Even public-facing analytics keys follow this pattern, as seen in apps/sim/lib/posthog/server.ts, which checks process.env.NEXT_PUBLIC_POSTHOG_ENABLED and NEXT_PUBLIC_POSTHOG_KEY to conditionally enable PostHog tracking.

The codebase enforces strict validation of required environment variables. If API_ENCRYPTION_KEY is missing when attempting cryptographic operations, the system throws explicit errors rather than falling back to defaults or unencrypted storage modes.

AES-256-GCM Encryption Primitives

For secrets that must persist in the database, SimStudio AI Sim provides a dedicated encryption layer in packages/security/src/encryption.ts. This module exports encrypt and decrypt functions that use AES-256-GCM, a symmetric encryption algorithm providing both confidentiality and authenticity.

The implementation returns a self-contained string format: iv:encrypted:authTag. This concatenated format stores the initialization vector (IV), ciphertext, and authentication tag together, eliminating the need for separate storage columns while maintaining cryptographic integrity.

import { encrypt } from '@sim/security';

// The encryption key is loaded from environment variables
const key = Buffer.from(process.env.API_ENCRYPTION_KEY!, 'utf8');
const { encrypted, iv, authTag } = await encrypt('super-secret-api-key', key);
// Store as: `${iv}:${encrypted}:${authTag}`

The encryption key itself is never committed to the repository; the application expects API_ENCRYPTION_KEY to be provided through the deployment environment.

Isolated Token Verification

Authentication verification follows the principle of minimal privilege. Rather than exposing full authentication configurations to services that only need to verify tokens, the platform uses packages/auth/src/verify.ts to create a lightweight Better Auth instance specifically for validation purposes.

The createVerifyAuth function accepts only the secret and base URL required for token verification, consuming process.env.BETTER_AUTH_SECRET and process.env.NEXT_PUBLIC_APP_URL. This approach allows background workers and API routes to verify one-time tokens without accessing the complete authentication provider configuration.

import { createVerifyAuth } from '@sim/auth';

const verifyAuth = createVerifyAuth({
  secret: process.env.BETTER_AUTH_SECRET!,
  baseURL: process.env.NEXT_PUBLIC_APP_URL!,
});

const { valid, payload } = await verifyAuth.oneTimeToken.verify(token);

Encrypted Storage and Migration Workflows

API keys and other sensitive credentials are stored in the database only in encrypted form. The api_key column contains the iv:encrypted:authTag string generated by the encryption utilities.

When backfilling or migrating credentials, dedicated scripts handle decryption and re-encryption securely:

These scripts maintain the same strict environment variable dependency, failing immediately if API_ENCRYPTION_KEY is unavailable.

Secure Testing Practices

Test suites avoid using real credentials by mocking process.env values. In apps/sim/tools/http/request.test.ts and apps/sim/tools/index.test.ts, the test environment replaces sensitive configuration with mock values and resets the environment after each test execution.

This pattern prevents accidental secret leakage in CI/CD logs while ensuring tests validate the actual secret-handling code paths.

Summary

SimStudio AI Sim's secrets and credential management strategy provides multiple defense layers:

  • Environment-only configuration: All secrets enter via process.env with no hard-coded fallbacks.
  • Strong encryption: AES-256-GCM protects all credentials at rest with authenticated encryption.
  • Minimal exposure: Token verification uses isolated Better Auth instances with limited configuration scope.
  • Fail-secure design: Missing encryption keys trigger explicit errors rather than silent unencrypted fallbacks.
  • Auditable migrations: Database scripts centralize cryptographic operations in version-controlled, reviewable files.

Frequently Asked Questions

What encryption algorithm does SimStudio AI Sim use for credential storage?

The platform uses AES-256-GCM (Galois/Counter Mode) as implemented in packages/security/src/encryption.ts. This provides 256-bit symmetric encryption with built-in authentication, storing data in the format iv:encrypted:authTag to ensure integrity alongside confidentiality.

How should I rotate the API_ENCRYPTION_KEY in a production deployment?

Rotation requires running migration scripts like backfill-api-key-hash.ts or migrate-block-api-keys-to-byok.ts. These scripts decrypt existing credentials using the old key and re-encrypt them with the new key. You must provide the new key via environment variables before deployment and ensure zero-downtime rotation by temporarily accepting both keys during the transition window.

Why does the codebase use a separate verify.ts for Better Auth instead of the main auth configuration?

The createVerifyAuth function in packages/auth/src/verify.ts creates a minimal Better Auth instance that only handles token verification. This reduces the attack surface by not exposing full authentication provider configurations to services that merely need to validate tokens, following the principle of least privilege.

Are secrets ever logged or exposed in test outputs?

No. Test files like apps/sim/tools/http/request.test.ts explicitly mock process.env values with non-sensitive placeholders. The test utilities reset environment mocks after each test, ensuring production secrets never appear in logs, error traces, or test reports.

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 →