Secrets

Pipelines need credentials to call external services, and those credentials must not leak into places that outlive a run. This page covers the keys that encrypt them, the rules that keep them out of logs, state, and API responses, and the frontend rule for displaying them.

Encryption keys

  • Fernet symmetric encryption is keyed from the FERNET_KEY environment variable
  • FERNET_KEY is separate from SECRET_KEY, which is used exclusively for signing JSON Web Tokens (JWTs). The keys have distinct cryptographic purposes.
  • Key rotation for connector credentials must not require JWT session invalidation, and vice versa
  • The backend refuses to start if either key is absent or malformed: SECRET_KEY must be at least 32 bytes, and FERNET_KEY must be a valid Fernet key (32 url-safe base64-encoded bytes)

Never logged or returned

Secrets are never logged and never returned in API responses.

Credential-in-state rule

Decrypted connector credentials and model backend API keys must never enter LangGraph state, checkpoint blobs, OpenTelemetry span attributes, or log output. Connectors receive the decrypted credential in-process only (via a transient context object), use it for the API call, and do not serialize it.

Secrets backends

MODULO_SECRETS_BACKEND selects where connector credentials and model backend API keys are stored. The default is fernet. The two external backends are available on every tier and are never license-gated.

Secrets backends
Backend Stores secrets in Configuration
fernet (default) The Farna Control database, encrypted at rest FERNET_KEY
vault HashiCorp Vault KV v2 VAULT_ADDR, plus VAULT_TOKEN or VAULT_ROLE_ID and VAULT_SECRET_ID. Needs the optional hvac package
aws AWS Secrets Manager The AWS credential chain (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, or AWS_PROFILE), plus AWS_REGION (default us-east-1). Needs the optional boto3 package

Vault also reads VAULT_MOUNT_POINT (default secret) and VAULT_PATH_PREFIX (default modulo/secrets). An unknown backend name is rejected with an error naming the three valid values, and the Vault backend refuses to construct without VAULT_ADDR rather than falling back to fernet.

The Fernet backend partitions secrets by organization. Vault and AWS Secrets Manager resolve a global key namespace and cannot partition by organization, so on a multi-org deployment (MODULO_MULTI_ORG_ENABLED=true) a secretref:// credential reference is refused with a typed error when the backend is Vault or AWS. One organization can then never read another’s secret. A single-org deployment, the default, is unaffected.

At-rest encryption

With the Fernet backend, connector credentials are stored encrypted with Fernet symmetric encryption, keyed by FERNET_KEY, and decrypted only in-process at run start (see the credential-in-state rule above). With the Vault or AWS backend, the value lives in that external store and Farna Control reads it at run start instead.

Sensitive values in the DOM

Sensitive field values (API key secrets, connector credentials, webhook secrets, model backend API keys) must never exist in the Document Object Model (DOM) in plaintext unless the user has explicitly completed a server-authenticated reveal action.

  • Sensitive values render as ●●●●●●● in the DOM by default
  • A reveal action calls the server; the server verifies authentication and returns the value in the API response body
  • The frontend injects it into the DOM for a time-limited display window (default 30 seconds)
  • Connectors: tool integrations for pipeline nodes
  • Model Backends: large language model (LLM) routing and failover
  • Configuration: environment variables and backend setup
  • Single Sign-On: where the Single Sign-On (SSO) client secret is stored at rest
  • SCIM Provisioning: where the System for Cross-domain Identity Management (SCIM) bearer token is stored at rest