Introduction
Ansible Core 2.22.0 was published on 2026-11-02, succeeding 2.21.5. This is a major release that introduces automatic secret masking across display output, module logging, and callback plugin task results, along with controller Python version changes. The full changelog is available at CHANGELOG-v2.22.rst, and the porting guide covers the upgrade path in detail.
Whats New
Secret Masking
The headline feature of this release is automatic secret masking. Ansible now redacts known secret values from any output it generates, including display output (verbose, warning, deprecation, and error messages), module logging, and task results passed to callback plugins. Masking is non-destructive: the real value stays available to tasks, conditionals, and registered variables, but anything rendered to the user is replaced with $REDACTED$.
Key points about this feature:
- A new public API,
ansible.module_utils.secrets, exposesregister_secretandregister_secretsto manually register values for redaction, plusmask_secretsto redact registered secrets from a string. This works both on the controller and inside Python modules. - PowerShell modules get an equivalent via the new
Ansible.SecretsC# module_util, with[Ansible.Secrets.SecretMasker]::RegisterSecret()andMaskString(). - Secrets registered inside a module or worker process propagate back to the controller, so they are masked there too.
- Callback plugins now always receive task results with registered secrets replaced by
$REDACTED$. TheANSIBLE_SUPPORTS_MASKINGcallback class attribute, introduced in 2.22.0b1 for plugins that wanted unmasked results, has been removed and is now ignored. - The minimum and maximum secret length limits from 2.22.0b1 betas have been removed. Secrets of any length are registered and redacted wherever they appear; short secrets are no longer restricted to whole-word matches, and long secrets are matched on their full value instead of being truncated to the first 65536 characters. Surrounding whitespace is still stripped before registration, and empty-after-stripping values are ignored.
- A new internal config option,
_SECRETS_INPUT_FILES, pre-seeds values to redact fromansible,ansible-playbook, andansible-consoleoutput. Each file is YAML or JSON with aversionkey (currently1) and asecretskey listing string values to mask. If the file has the executable bit set, it is run instead of read, and its stdout is parsed as the document.
The following values are now automatically registered as secrets and redacted from masked output:
- Vault passwords supplied by prompt, file, or script
- The decrypted plaintext of vault-encrypted values, and every string or numeric value in a vault-encrypted vars file
- Passwords entered for
--ask-passand--ask-become-pass no_logmodule option values- The
become_passoption of thesudo,su, andrunasbecome plugins - The
password,private_key, andprivate_key_passphraseoptions of thesshconnection plugin - The
passwordoption of thewinrmandpsrpconnection plugins, and thecertificate_key_passwordoption ofpsrp - The
passwordoption of theurllookup - Values returned by the
passwordandunvaultlookups - The secret passed to the
vaultandunvaultfilters - User input of the
pauseaction whenechoisfalse - Values entered for a play
vars_promptwhenprivateistrue(the default, unchanged)
Python Support Changes
- Adds support for Python 3.15.
- Drops support for Python 3.12 on the controller.
Other Minor Changes
- A new
OrderedSetclass is available for situations where a unique, ordered list is needed. - Role and play argument spec validation now supports
no_log. Variables labeledno_logare redacted from masked output (issue #84498). ansible-galaxynow sortsFILES.jsonwhen building a collection, for reproducible build artifacts.
Release Artifacts
| Artifact | Size | SHA256 |
|---|---|---|
| ansible_core-2.22.0-py3-none-any.whl | 2488530 bytes | 8285d4cc81c3e3eb2d954e75531724fe0ae154d228475638123451f034a74657 |
| ansible_core-2.22.0.tar.gz | 3476434 bytes | bf50b4a0cfa985e30585c7ba301897ea7050d224ca49d2816cab10e33a160e1c |
How to Install and Test
Ansible Core 2.22.0 requires a controller running Python 3.13 or newer, since Python 3.12 support on the controller has been dropped. Verify the Python version before upgrading, then install in a virtual environment to test alongside existing installations.
# check current Python version on the controller
python3 --version
# create an isolated virtual environment for testing
python3 -m venv ansible-2.22-test
source ansible-2.22-test/bin/activate
# install ansible-core 2.22.0 explicitly
pip install ansible-core==2.22.0
# verify the installed version
ansible --version
# optionally verify the downloaded wheel checksum
sha256sum ansible_core-2.22.0-py3-none-any.whl
# run a quick playbook to confirm secret masking behavior
ansible-playbook -i localhost, -c local test-secrets.yml --ask-vault-pass
When testing, pay particular attention to any custom callback plugins. Plugins relying on ANSIBLE_SUPPORTS_MASKING to receive unmasked results will now always get masked output, since that attribute has been removed and is ignored in 2.22.0. Review _SECRETS_INPUT_FILES if pre-seeding additional secrets for redaction is needed, and consult the porting guide for the complete list of breaking changes before rolling this out to production control nodes.