🔐 Encrypted Configuration Values with bxsecret: — BoxLang 1.17.0

BoxLang 1.17.0 introduces a clean, explicit way to store encrypted values directly in your JSON configuration files, Application.bx settings, environment variables, and more.

The Problem

You’ve always been able to put passwords, API keys, and other secrets into your boxlang.json or Application.bx, but they were in plaintext — sitting on your hard drive for everyone to see. Workarounds like environment variable indirection helped, but didn’t give you a native way to encrypt sensitive values at rest.

The Solution: bxsecret: Prefix

BoxLang 1.17.0 introduces a simple convention: any configuration value prefixed with bxsecret: is automatically decrypted at runtime. Plaintext values continue to work unchanged.

In boxlang.json

{
  "mySetting" : "bxsecret:wfYldsN1NOxSAC6k6H4RKg=="
}

In Application.bx

bx:application
    datasources = {
        "myDSN" = {
            driver     = "mssql",
            host       = "localhost",
            port       = "1433",
            database   = "master",
            username   = "sa",
            password   = "bxsecret:wfYldsN1NOxSAC6k6H4RKg=="
        }
    };

In Environment Variable Overrides

BOXLANG_DATASOURCES_myDSN_password=bxsecret:wfYldsN1NOxSAC6k6H4RKg==

Generating an Encrypted Value

Use the BoxLang CLI to create a paste-ready secret:

boxlang generatesecret my-sensitive-value

The command prints a bxsecret:xxx value using the seed and algorithm active for that runtime. Drop it directly into any config location.

How the Encryption Seed Works

When BoxLang first needs to decrypt a secret, it automatically creates an encryption seed and stores it at:

<boxlang-home>/config/.seed

This file must be retained and protected — it’s required to decrypt values generated by that runtime. Without it, your secrets can never be recovered.

Using a Specific Seed

Need the same secrets to work across multiple runtimes (e.g., dev → staging → production with pre-encrypted values)? Generate a compatible seed:

seed = generateSecretKey();

Place it in <boxlang-home>/config/.seed, then run boxlang generatesecret using that runtime to create values. Deploy the same .seed file to every runtime that needs to decrypt those values.

You can also set the seed via environment variable (useful for containerized deployments):

BOXLANG_SECURITY_SECRETSEED=<generated-seed>

Important Security Notes

  • Every BoxLang installation generates a unique secret seed automatically.
  • The same input string produces a different encrypted output on different seeds — so a stolen config file can’t be decrypted on another instance without its seed.
  • Anyone with the seed can decrypt secrets generated from it. Protect .seed files and BOXLANG_SECURITY_SECRETSEED accordingly.
  • The seed can also be set in boxlang.json via security.secretSeed, but we don’t recommend it — keeping the seed out of the main config is better security practice.

Encryption Algorithm

By default, BoxLang uses a strong algorithm, but you can configure it:

{
  "security" : {
    "secretAlgorithm" : "AES"
  }
}

security.secretAlgorithm must remain in plaintext. When using a non-default algorithm, generate a compatible key and use the same algorithm wherever the related bxsecret: values are generated or read.

Where Can You Use bxsecret:?

The encrypted prefix works in nested structs and arrays within:

  • boxlang.json — any setting value
  • Environments variable overridesBOXLANG_SETTING_NAME=bxsecret:xxx
  • JSON env var placeholders"setting" : "${SOME_ENV_VAR}" where the env var contains a bxsecret: value
  • Application.bx / Application.cfcthis settings
  • bx:application component attributes
  • Datasource definitions, cache settings, mappings — any nested application setting

Secrets are resolved transparently — they’re available to normal configuration and placeholder behavior before a setting is used.

Compatibility & Security Model

Feature Behavior
Detection Explicit — BoxLang does not guess whether a string is encrypted. Only bxsecret: prefixed values are decrypted.
Drop-in replacement A bxsecret: value can replace a plaintext value without changing the surrounding structure.
Backward compat Plaintext values continue to work exactly as before.
What to encrypt Any and every config value — not just passwords. If your organization treats database usernames as secrets, encrypt those too.

Quick Start

# Step 1: Generate an encrypted value
boxlang generatesecret "SuperSecretPassword123!"

# Output: bxsecret:wfYldsN1NOxSAC6k6H4RKg==

# Step 2: Use it in config
{
  "api" : {
    "key" : "bxsecret:wfYldsN1NOxSAC6k6H4RKg=="
  }
}

That’s it. BoxLang decrypts it at runtime — your code never needs to change.


Stay tuned for more 1.17.0 feature spotlights.

Really great feature. I wish we had this facility in Coldfusion.
Yes. Yes. I will get around to using BoxLang very soon :star_struck:

1 Like