Skip to content

Secret Security & Limitations

dotenv-fusion controls when secret values are resolved and where it writes them. The surrounding shell, process, operating system, editor, and generated artifacts remain part of the security boundary.

Runtime resolution

  • The store name is fixed in the current age://store/... contract.
  • The age store defaults to secrets beside the main .env-fuse.
  • A store configured in the parent environment takes priority over one declared in .env-fuse.
  • Relative store paths are resolved from the main .env-fuse, not the process working directory.
  • References are confined beneath the canonical store path after resolving .. and symbolic links.
  • The age executable and identity paths come from the parent environment or explicit CLI options. .env-fuse cannot replace them for the current run.
  • Decrypted bundles are cached only in memory for the current invocation.

Bundle directives, duplicate keys, invalid UTF-8, and variable expansion are rejected. Only keys selected by #@def ... source= enter the resolved environment.

Diagnostics and output

Secret values and values derived from them are masked transitively in verbose, --debug, --typed, fuse --diff, and error output. Public source URIs and variable names can still appear because they define the configuration contract.

load is an intentional plaintext channel: it emits real values as shell or JSON output. Use Run an Application when a command can receive its configuration directly.

Plaintext artifacts

fuse resolves secret sources before writing the compiled file:

dotenv-fusion fuse -f .env-fuse -o .env.production

The file contains real plaintext values. New files use mode 0600 on POSIX; existing permissions are preserved. --stdout and --load also emit real values.

The review modes do not print resolved values:

dotenv-fusion fuse -o .env.production --dry-run
dotenv-fusion fuse -o .env.production --diff

--dry-run resolves and validates without writing. For source-backed configurations, --diff masks every assignment value because an existing artifact's secret provenance may no longer be known.

Editing boundary

secret edit needs a plaintext temporary file so an external editor can open the bundle. The temporary workspace is removed on normal exits and handled failures, but RAM-backed storage can still be swapped or captured by hibernation. An uncatchable termination or machine crash can leave temporary data behind. Editors can also create their own backups or histories.

Use exec for runtime delivery when no plaintext file is required. Use secret edit only on a machine and temporary filesystem appropriate for the secret material.