Skip to content

Hardened Mode — Startup Security Enforcement in Xferity MFT

Hardened mode is a configuration-enforcement layer that causes Xferity to fail at startup if any security requirement is not met. It is designed for production deployments where configuration drift, plaintext secrets, or insecure transport options are unacceptable.

Hardened mode is opt-in. Development and staging environments can run without it.

security:
hardened_mode: true

With runtime flag (no config change required):

Terminal window
xferity run-service --expect-existing-state

Note: security.hardened_mode in config and --expect-existing-state on the CLI are separate but complementary controls, described below.

When security.hardened_mode: true, Xferity performs the following checks at startup. Any violation causes startup to fail with an error message. There is no silent degradation.

Xferity scans the config YAML for these key names:

  • password
  • passphrase
  • private_key
  • token
  • secret
  • api_key
  • apikey
  • sendgrid_api
  • default_webhook_url
  • dsn
  • auth_token
  • metrics_token

If any of these keys contains a literal value (not a secret reference), startup fails.

Allowed values: Secret references using env:, file:, vault:, aws-sm:, azure-kv:, local-vault:, or literal: prefixes.

Example — rejected in hardened mode:

sftp:
password: MySecretPassword123 # REJECTED

Example — accepted in hardened mode:

sftp:
password: env:SFTP_PASSWORD # OK — resolved at runtime

2. No plaintext secrets in flow YAML files

Section titled “2. No plaintext secrets in flow YAML files”

All flow YAML files in the flows_path directory are scanned at startup. The same key list applies. If any flow contains a plaintext secret, startup fails with the file name and key path.

Flow secret keys that trigger rejection:

  • password, passphrase, token, secret, api_key, apikey, private_key
  • Any key ending in _password, _passphrase, _token, _secret, _api_key, _private_key

When using the PostgreSQL state backend, sslmode: disable is rejected. The minimum accepted value is sslmode: require.

# REJECTED in hardened mode:
state:
postgres:
sslmode: disable
# Required minimum:
state:
postgres:
sslmode: require

The default sslmode is require when not configured explicitly.

4. Auth credentials must be secret references

Section titled “4. Auth credentials must be secret references”
  • auth.local.password_ref must use env:, file:, or vault: prefix
  • auth.oidc.client_secret must use env:, file:, or vault: prefix

A literal password or client secret in the auth config causes startup to fail.

5. Licensing API token must be a secret reference

Section titled “5. Licensing API token must be a secret reference”

When licensing.online_sync.enabled: true:

  • licensing.online_sync.api_token must use env:, file:, or vault: prefix
  • Online sync endpoint must use HTTPS

In hardened mode, the security posture engine escalates these findings from warning to error:

FindingNormal severityHardened severity
sftp_insecure_host_keywarningerror
sftp_insecure_host_key_globalwarningerror
ftps_tls_skip_verifywarningerror
as2_tls_skip_verifywarningerror

This means any SFTP partner with allow_insecure_host_key: true, any FTPS partner with tls.insecure_skip_verify: true, or any AS2 partner with https_tls.insecure_skip_verify: true causes the posture report’s healthy field to be false.

This CLI flag is a separate hardened-deployment control:

Terminal window
xferity run-service --expect-existing-state

When this flag is set, Xferity fails at startup if the licensing state file is absent. The licensing state file is written during the first successful startup and contains runtime activation state.

Why this matters: An attacker who gains operating system access and deletes the state file would otherwise cause Xferity to start with a clean slate, potentially bypassing license enforcement checks. The --expect-existing-state flag prevents this: if the state file is missing on a node that has previously run, startup is refused.

Use this flag on all hardened production nodes after their initial deployment. On first deployment (before any state file exists), run without this flag to allow startup.

You can also set it in config:

licensing:
expect_existing_state: true
security:
hardened_mode: true
state:
backend: postgres
postgres:
host: db.internal
user: xferity
dbname: xferity
password: env:XFERITY_DB_PASSWORD
sslmode: require
auth:
mode: local
local:
username: admin
password_ref: env:XFERITY_ADMIN_PASSWORD
audit:
enabled: true
path: /var/log/xferity/audit.jsonl
tamper_evidence_enabled: true
secrets:
local_vault:
master_key_ref: env:MFT_MASTER_KEY

What hardened mode does not protect against

Section titled “What hardened mode does not protect against”

Hardened mode is one layer of defense. It does not replace:

  • Network controls — restrict access to SFTP port 22, the Xferity UI port, and the database port via firewall rules
  • File system permissions — protect config files, key files, and the audit log directory with appropriate OS permissions
  • Certificate lifecycle management — use the posture engine and monitoring to catch expiring certificates before they cause failures
  • Access governance — control who has administrative access to the Xferity UI and the underlying host
  • Backup and disaster recovery — regularly back up the PostgreSQL database and audit log

Run validation before deploying:

Terminal window
xferity validate --config /etc/xferity/config.yaml

This runs all the same startup checks, including hardened mode enforcement, without starting any services.

Use dry-run to test flows without transferring files:

Terminal window
xferity run my-flow --dry-run