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
.seedfiles andBOXLANG_SECURITY_SECRETSEEDaccordingly. - The seed can also be set in
boxlang.jsonviasecurity.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 overrides —
BOXLANG_SETTING_NAME=bxsecret:xxx - JSON env var placeholders —
"setting" : "${SOME_ENV_VAR}"where the env var contains abxsecret:value Application.bx/Application.cfc—thissettingsbx:applicationcomponent 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.