# New Secret Masking Feature - 2.22

**URL:** <https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291>\
**Category:** Project Discussions\
**Tags:** security, ansible-devel, ansible-core\
**Created:** [September 11, 2026, 2:55am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291 "2026-09-11T02:55:05Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 11, 2026, 2:55am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/1 "2026-09-11T02:55:05Z")

</div>

# New Ansible 2.22 Feature - Secret Masking

A new feature has just been merged in `devel` for `ansible-core`, a secret registration and masking system. The initial implementation is in [ansible/ansible#87457](https://github.com/ansible/ansible/pull/87457) and the documentation is in review at [ansible/ansible-documentation#3934](https://github.com/ansible/ansible-documentation/pull/3934). We would love feedback from anyone who can try it on `devel` before release, especially collection maintainers with custom modules or callback plugins.

Big shout out to @pkingstonxyz and @mkrizek for bringing this feature over the time.

## What it is

Ansible keeps a registry of secret values for the life of the process. Any text that leaves Ansible through display output (screen and `log_path`), callback plugin results, or module logging on the managed node has registered secrets replaced with `$REDACTED$`.

Unlike the old `VALUE_SPECIFIED_IN_NO_LOG_PARAMETER` on module values with `no_log=True`, masking is now non-destructive. Variables, module arguments, and task results keep the real value which can be used in registered variables. Only the rendered output through callbacks of `display` calls will redact those value.

Values are registered automatically from various sources; vault content and passwords, `no_log` module options, `vars_prompt` and `--ask-*` prompts, connection and become passwords, and the `password`/`unvault` lookups and `vault`/`unvault` filters. Secrets can also be manually registered with the new `register_secret` filter plugin.

## What it looks like

Two new filters, `register_secret` and `mask_secrets`, cover anything Ansible does not register for you:

```yaml
- name: Generate a database password
  ansible.builtin.command: openssl rand -base64 32
  register:
    db_password: _task.result.stdout | register_secret
    password_result: _task.result
  no_log: true

- name: Usable, but masked in output
  ansible.builtin.debug:
    msg: "Setting database password to {{ db_password }}"

```

The last task prints `Setting database password to $REDACTED$`, and `db_password` still holds the real value for later tasks. Use `mask_secrets` when writing output somewhere Ansible does not control, such as a file on a target.

## What it means for end users

- `no_log` module options no longer return `VALUE_SPECIFIED_IN_NO_LOG_PARAMETER` in results. The real value is kept and masked only in output. Update any playbooks or tests that check for that placeholder.
- The `no_log` task keyword is unchanged and still censors the whole task result. It does not register anything, so pair it with `register_secret` if a later task uses the value.
- Secrets shorter than 4 characters are never masked to avoid collisions in normal out, and 4 to 6 character secrets are only masked as whole words. Only exact matches are masked, so hashed or base64 copies are not.
- This is best effort and a safety net, not a replacement for Vault and `no_log` if you encounter one of the known limitations

## What it means for module and plugin developers

- A new public API in `ansible.module_utils.secrets` works in modules and all controller plugins:

```python
from ansible.module_utils.secrets import register_secret, mask_secrets

token = register_secret(session['token']) # returned unchanged, masked in output

mask_secrets(f"API Token Result {token}") # API Token Result $REDACTED$

```

PowerShell modules get the same via the `Ansible.Secrets` C# util with `[Ansible.Secrets.SecretMasker]::RegisterSecret()` and `::MaskString()`.

- Plugin options can be marked `secret: true` so the value is registered regardless of which source set it. Use this for any password or token option.
- Callback plugins should set `ANSIBLE_SUPPORTS_MASKING = True` on the class and mask the results themselves. Callbacks that set it receive unmasked results and must mask anything written outside `Display` with `mask_secrets()`. Callbacks that do not set it keep receiving pre-masked results through a compatibility shim that will be deprecated and removed in a future release.
- `heuristic_log_sanitize()`, `remove_values()`, and `sanitize_keys()` are deprecated for removal in 2.25. `AnsibleModule.log()` and `run_command()` no longer apply the old password heuristics, so register any secret passed on a command line that is not a `no_log` option.

Full details, including the length rules and limitations, are in the documentation PR [Add documentation for secret masking by jborean93 · Pull Request #3934 · ansible/ansible-documentation · GitHub](https://github.com/ansible/ansible-documentation/pull/3934) that is not yet live.

## Known Problems

This is a list of known problems in the current implementation that we are aiming to either fix or explicitly document as a known limitation:

- ~~Module journalctl/syslog of invocation args do not redact module options with a value less than 4 characters in suboptions~~ Edit: Merged into devel
  - This will be fixed to keep compatibility with existing Ansible versions
  - We will not be registering these short values as secrets for the display output, only the syslog/journalctl behaviour is being kept
  - PR opened [Redact syslog secrets regardless of length by jborean93 · Pull Request #87517 · ansible/ansible · GitHub](https://github.com/ansible/ansible/pull/87517)

- A failure in `register_secrets` filter that contains the literal value leaks in the Ansible error origin statement - `{{ 12345678 | register_secret }}` (fails due to being non-str)
  - Still trying to find the best way forward for this
  - PR opened [Redact content if any error has show\_content=False by jborean93 · Pull Request #87548 · ansible/ansible · GitHub](https://github.com/ansible/ansible/pull/87548)

- ~~`register_secrets` filter only fails for invalid types, shorter secrets are silently ignore~~ : Edit: Merged into devel
  - As this is an explicit action by module authors we should do some validation here
  - PR opened [register\_secret - check length and add validation kwarg by jborean93 · Pull Request #87529 · ansible/ansible · GitHub](https://github.com/ansible/ansible/pull/87529)
  - Default behaviour is to error but can be configured to warn/ignore
  - Note this still only applies to the filter, implicit secret registration behaviour is unchanged for backwards compatibility.

I’ll be editing this section so it should stay up to date.

---

<div class="post-metadata">

**Author:** ![Jeff\_Pullen](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jeff_pullen/32/5318_2.png) [@Jeff\_Pullen](https://forum.ansible.com/u/Jeff_Pullen)\
**Post date:** [September 11, 2026, 10:49pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/2 "2026-09-11T22:49:59Z")

</div>

Nice work on this, and the non-destructive part especially.

A question about the length floor. A value under four characters is discarded at registration with no warning and no error, and `register_secret` returns it unchanged either way, so nothing tells the author it did not take effect. The value then prints in full.

The floor assumes the threat is guessing the value, where three characters is no keyspace. Plenty of short values are not credentials at all: an environment code, a customer or org short name, a subdomain. Nobody needs to guess those. What matters is that the string shows up in a log that goes into a support ticket or a public CI job, and no longer value is available, because it is the author’s org name.

So the behavior is fail open, silently, for everyone. Over-redacting costs a log that is hard to read. Under-redacting publishes something explicitly marked as not for publication.

Is fail open the right thing to hard code here, or should it be a policy with a fail safe default? A warning would be the minimum. `_log_invocation` already takes the other path for `no_log` params, blanking them rather than trusting the masker, which seems like the right instinct.

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 12, 2026, 6:34am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/3 "2026-09-12T06:34:21Z")

</div>

The main problem with redacting short strings is that they tend to easily show up randomly in other strings. If you end up seeing `$REDACTED$` in some Base64 encoded output because that 2- or 3-letter “secret” sequence randomly shows up in data, this is at least annoying and sometimes dangerous (since you can’t use the Base64 output anymore since you don’t know its actual value).

(This is also a reason why I would have preferred to use tagging over value redaction, since then you can also tag a one-letter string as secret without it resulting in that letter being redacted everywhere, but the problem with this approach is that it misses many places where this secret value shows up in, like composed URLs which contain username + password.)

Other services that redact strings from output, like GitLab CI redacting secrets from CI log, also only redact strings that have a certain length (and format, I think it also requires you to not use spaces IIRC).

(I’m waiting for the first person to use four spaces as a sensitive value somewhere, and then wondering why they end up having `$REDACTED$` all over the place in output where something is indented by at least four spaces… I saw some issues where people complained that parts of URLs/data/… got censored in module output when they used apparently trivial passwords for `no_log` inputs, that happened to be similar to other strings that showed up. Like password `test` and URL `test.example.com`, where “obviously” the second `test` is totally unrelated to the first `test` and why on earth got the second one redacted?!)

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 12, 2026, 2:15pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/4 "2026-09-12T14:15:54Z")

</div>

> I’m waiting for the first person to use four spaces as a sensitive value somewhere, and then wondering why they end up having `$REDACTED$` all over the place in output where something is indented by at least four spaces…

After reading the proposed docs again ([Add documentation for secret masking by jborean93 · Pull Request #3934 · ansible/ansible-documentation · GitHub](https://github.com/ansible/ansible-documentation/pull/3934)), I noticed it explicitly says “Leading and trailing whitespace is not part of a secret.”, so this won’t be a problem 🙂

* * *

There’s another thing I’ve been wondering about. Assume that there’s a module which returns a secret (for example, some token). Until now, a user might have chosen to run the module, register its result, and show the result using the `ansible.builtin.debug` action (and then they copy’n’paste it to some secret store), instead of using a module like `ansible.builtin.copy`/`ansible.builtin.template` or others to write it to a file (unencrypted or encrypted) or directly send it to a secrets store (OpenBao, Bitwarden, HC Vault, …).

Until now, this worked fine. But if now the module is changed to register that secret as a secret, suddenly the playbook will no longer show that secret to stdout, but instead show `$REDACTED$`. And there doesn’t seem to be a way to get Ansible to still print this secret unredacted.

Maybe it would be a good idea to explicitly mention this in the porting guide, in case someone’s workflow relies on this.

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 14, 2026, 3:39am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/5 "2026-09-14T03:39:03Z")

</div>

> [@Jeff\_Pullen](#):
>
> A question about the length floor. A value under four characters is discarded at registration with no warning and no error, and `register_secret` returns it unchanged either way, so nothing tells the author it did not take effect. The value then prints in full.

The floor here was a difficult choice to come to but it was decided to avoid false positive redactions on shorter strings that may not be a secret/sensitive value. IT is full of acronyms so 3 characters really does increase the chance for this happening. 4 was mostly chosen because pin codes usually are around 4 characters and the word boundary check we added was found to be a good middle ground but we can certainly understand the pros and cons behind lowering the floor.

The primary goal was more for redacting credentials and other private/secret values. I can see the desire for trying to redact personal and identifying information but I think this feature isn’t designed for this purpose.

@felixfontein has certainly hit the nail on the head though. We’ve found that shorter secrets were commonly conflicting with plaintext values which makes it trivial for someone to deduce what is a secret from what they expect to be in that plaintext.

> [@Jeff\_Pullen](#):
>
> Is fail open the right thing to hard code here, or should it be a policy with a fail safe default? A warning would be the minimum

We debated this but as the warning cannot contain the value itself the warning would essentially be generic. Generic warnings are de-duplicated in Ansible so subsequent triggers would be ignored breaking the purpose of the warning in the first place. There’s also a lot of secret registrations that are done implicitly that the user cannot control so a warning without that secret value in the text would be close to useless for tracking down and just extra noise for end users.

Turning this into an error is also not viable due to that implicit registration. Playbooks that work today would fail with such errors in the case where a secret that is too short is attempted to be registered. Even worse is that there would be no way to selectively turn it off for individual modules of registration points.

I do think we could at least error in the `register_secret` filter which is a new plugin so has no backwards compatibility concerns and is always a user defined registration rather than an implicit one done by the plugin author. I’m still unsure whether the default behaviour would be to error (would be my pick right now), warn, or ignore but having a `kwarg` to control that is probably the best choice.

> [@Jeff\_Pullen](#):
>
> `_log_invocation` already takes the other path for `no_log` params, blanking them rather than trusting the masker, which seems like the right instinct.

This was chosen to ensure the masking did not regress on the logging side which had access to the `no_log` information and was scoped in a way that we could still redact the information.

It’s certainly not ideal but this was ultimately the reasoning behind why we don’t fail or warn.

> [@felixfontein](#):
>
> Until now, this worked fine. But if now the module is changed to register that secret as a secret, suddenly the playbook will no longer show that secret to stdout, but instead show `$REDACTED$`. And there doesn’t seem to be a way to get Ansible to still print this secret unredacted.
> 
> Maybe it would be a good idea to explicitly mention this in the porting guide, in case someone’s workflow relies on this.

Thank you for bringing this up, we should definitely point this out in the porting guide and I’ll update the docs PR sometime shortly with this point. It might be nice for an extra option to the `debug` actions to tell it not to go through the redaction for such scenarios but from a technical perspective the masking happens beyond the `debug` action so would require a lot more thought on how to actually work. We’ve also hit the feature freeze for 2.22 so would be hard to sell, especially if the solution isn’t a simple one.

---

<div class="post-metadata">

**Author:** ![kks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kks/32/10352_2.png) [@kks](https://forum.ansible.com/u/kks)\
**Post date:** [September 14, 2026, 7:15am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/6 "2026-09-14T07:15:55Z")

</div>

> [@jborean](#):
>
> It might be nice for an extra option to the `debug` actions

maybe new debug\_secret (or print\_secret) action not just and option to make it explicit?

---

<div class="post-metadata">

**Author:** ![kks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kks/32/10352_2.png) [@kks](https://forum.ansible.com/u/kks)\
**Post date:** [September 14, 2026, 8:34am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/7 "2026-09-14T08:34:45Z")

</div>

> [@jborean](#):
>
> Any text that leaves Ansible through display output (screen and `log_path`), callback plugin results, or module logging on the managed node has registered secrets replaced with `$REDACTED$`.

Maybe it is worth mentioning what ansible api (what functions) garanties what secrets will be redacted.

I understand that all secret registration is happening at runtime. But sometimes I know in advance that certain information is a secret (env vars). Is there planned way to register secrets or secret env vars before runtime (e.g. in ansible.cfg)

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 14, 2026, 9:21am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/8 "2026-09-14T09:21:12Z")

</div>

> [@kks](#):
>
> maybe new debug\_secret (or print\_secret) action not just and option to make it explicit?

The issue is the redaction happens on the main Ansible process and there is no mechanism to call a method on display to bypass redaction. It would require a new method or mechanism to tell the callback not to redact the secrets in the result and even then there’s no way selectively disable redaction, it would have to be on the whole result possibly exposing other secret values.

> [@kks](#):
>
> Maybe it is worth mentioning what ansible api (what functions) garanties what secrets will be redacted.

The documentation PR [Add documentation for secret masking by jborean93 · Pull Request #3934 · ansible/ansible-documentation · GitHub](https://github.com/ansible/ansible-documentation/pull/3934) should hopefully cover what you are looking for here. TLDR anything on `display` will go through the redaction call. Anything outside of builtin can also call this API but we’ve marked `display` and the module logging as the two egress points in Ansible itself.

> [@kks](#):
>
> I understand that all secret registration is happening at runtime. But sometimes I know in advance that certain information is a secret (env vars). Is there planned way to register secrets or secret env vars before runtime (e.g. in ansible.cfg)

There is technically an undocumented API we’ve added that may be used by `ansible-runner`. You can see it in the PR itself if you are interested but it is undocumented and we reserve the right to remove or change it at any time.

Nothing is stopping you from creating a custom callback or other plugin that runs at startup to register whatever secrets in any way you want.

---

<div class="post-metadata">

**Author:** ![kks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kks/32/10352_2.png) [@kks](https://forum.ansible.com/u/kks)\
**Post date:** [September 14, 2026, 10:09am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/9 "2026-09-14T10:09:11Z")

</div>

> [@jborean](#):
>
> Nothing is stopping you from creating a custom callback or other plugin that runs at startup to register whatever secrets in any way you want.

That is a nice idea I did not think of. Thanks for pointing that out

> [@jborean](#):
>
> There is technically an undocumented API we’ve added

I did not get this one. Are you saying that

> [@jborean](#):
>
> ```python
> from ansible.module_utils.secrets import register_secret, mask_secrets
> 
> ```

can change any moment? Or what do you mean by non public API?

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 14, 2026, 10:57am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/10 "2026-09-14T10:57:35Z")

</div>

> [@kks](#):
>
> Or what do you mean by non public API?

I’m referring to [\_SECRETS\_INPUT\_FILES](https://github.com/ansible/ansible/blob/5467293624690dbb5ecf8dc8f442fa3e3204fbc5/lib/ansible/config/base.yml#L73-L89) which is internal and could be subject to change. The module\_utils is a public API and won’t change without the usual deprecation process.

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 14, 2026, 7:19pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/11 "2026-09-14T19:19:00Z")

</div>

If I pass a secret marked with the `ansible.builtin.register_secret` filter (or any other mean) to a “generic” module argument like `description` (which isn’t marked as `no_log=True`), does the module also censor the secret value in its log output? And if it does: does ansible-core makes sure to only provide the module with secrets that are actually passed to the module, and not information on other secrets that are not passed?

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 14, 2026, 7:36pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/12 "2026-09-14T19:36:06Z")

</div>

> [@felixfontein](#):
>
> If I pass a secret marked with the `ansible.builtin.register_secret` filter (or any other mean) to a “generic” module argument like `description` (which isn’t marked as `no_log=True`), does the module also censor the secret value in its log output?

Yes it will.

> [@felixfontein](#):
>
> And if it does: does ansible-core makes sure to only provide the module with secrets that are actually passed to the module, and not information on other secrets that are not passed?

Yes that’s correct, when we build the module arguments we scan the module options that will be sent to the module for any registered secrets. Only secrets present in there will be provided to the module.

For example this playbook will result in the following in the syslog/journal

```yaml
- hosts: localhost
  gather_facts: false
  tasks:
  - ping:
      data: '{{ "testme" | register_secret }}'

```

```auto
Sep 01 00:00:00 jborean-dev ansible-ping[24798]: Invoked with data=$REDACTED$

```

What is not covered if when a secret is registered on the controller but not provided as any input to the module. The module won’t know that it is a secret and thus won’t be redacted in the logging side. We’ve added this already to the known limitations [ansible-documentation/docs/docsite/rst/playbook\_guide/playbooks\_secret\_masking.rst at 394c69fc765114e063418fbbcca975199b67af31 · jborean93/ansible-documentation · GitHub](https://github.com/jborean93/ansible-documentation/blob/394c69fc765114e063418fbbcca975199b67af31/docs/docsite/rst/playbook_guide/playbooks_secret_masking.rst?plain=1#L302-L304). This only applies to the module logging though, the results when it comes back to Ansible will still be redacted because Ansible knows about that secret.

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 14, 2026, 7:50pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/13 "2026-09-14T19:50:54Z")

</div>

> [@jborean](#):
>
> Yes that’s correct, when we build the module arguments we scan the module options that will be sent to the module for any registered secrets. Only secrets present in there will be provided to the module.

Great, thanks a lot for confirming that! I was expecting this answer, but having it confirmed is a lot better than hoping for it (and takes less time than figuring this out myself, which I will eventually do when I have enough time, but not now 😉 ).

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 16, 2026, 8:16pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/14 "2026-09-16T20:16:44Z")

</div>

One thing I noticed while looking more closely into callbacks: if the default callback is used with `result_format=yaml`, are task outputs always properly sanitized? Or more precisely: does PyYAML always encode keys and values so that they contain secrets either as-is, or JSON encoded?

---

<div class="post-metadata">

**Author:** ![jborean](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jborean/32/1525_2.png) [@jborean](https://forum.ansible.com/u/jborean)\
**Post date:** [September 17, 2026, 3:54am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/15 "2026-09-17T03:54:11Z")

</div>

I haven’t done an in depth look but YAML is certainly difficult as it escapes some control characters a bit differently and multilined values are indented at different levels to what the string will be. There’s also a few differences in how the libyaml C emitter works vs the python emitter.

We will have to have a closer look to decide on what we want to do here.

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 17, 2026, 4:42am UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/16 "2026-09-17T04:42:11Z")

</div>

There are multiple callbacks in community.general that call `self._dump_results()` and that can be configured to use YAML output, so they’ll have the same problem and would need the same / a similar solution. (That’s how I got interested in it in the first place…)

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 29, 2026, 4:39pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/17 "2026-09-29T16:39:50Z")

</div>

The documentation is now online BTW. The most important pages (users and devs):

- [Masking secrets in Ansible output — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/devel/playbook_guide/playbooks_secret_masking.html#playbooks-secret-masking)
- [Handling secrets in modules and plugins — Ansible Community Documentation](https://docs.ansible.com/projects/ansible/devel/dev_guide/developing_secret_masking.html)

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [October 3, 2026, 8:14pm UTC](https://forum.ansible.com/t/new-secret-masking-feature-2-22/46291/18 "2026-10-03T20:14:26Z")

</div>

I created a PR to extend the `validate-modules` `no_log` heuristic test (it forces you to add `no_log=True` or `no_log=False` to module options that look like they could contain secrets) for plugin options (you have to add `secret=true` or `secret=false` for similarly named plugin options). This could be helpful for other collection maintainers (even if it doesn’t make it into ansible-test) preparing for ansible-core 2.22.

Here’s the PR: [validate-modules: adopt no\_log=True/False test for secret=true/false, and ignore casing of option name for the test by felixfontein · Pull Request #87629 · ansible/ansible · GitHub](https://github.com/ansible/ansible/pull/87629)
