# Using Ansible to mitigate copy.fail

**URL:** <https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755>\
**Category:** Get Help\
**Created:** [April 30, 2026, 10:19am UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755 "2026-04-30T10:19:46Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [April 30, 2026, 10:19am UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/1 "2026-04-30T10:19:46Z")

</div>

Though I’d share this minimal Ansible role to mitigate [copy.fail](https://copy.fail) for people prior to the kernel updates being available:

```yaml
---
- name: Unload algif_aead kernel module
  community.general.modprobe:
    name: algif_aead
    state: absent
    persistent: absent
  register: copyfail_modprobe

- name: Reboot
  ansible.builtin.reboot:
  when: copyfail_modprobe.changed | ansible.builtin.bool
...

```

Create `roles/copyfail/tasks/main.yml` with the above content and run the role in check mode to see if anything needs doing and then run not in check mode if needed to update and reboot servers.

I was pleasantly surprised how minimal this was 🙂

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [April 30, 2026, 2:08pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/2 "2026-04-30T14:08:46Z")

</div>

you can also use a handler for reboot + notify, but this works fine too

---

<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:** [April 30, 2026, 2:45pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/3 "2026-04-30T14:45:14Z")

</div>

I’ve always wanted to ask. When one should use handlers? My opition - not in the roles.

This is my line of thinking - it is not good to put flush\_handlers inside role because you do not know what handlers you are flushing - there might be some existing before the role. So it is better to avoid them in the roles, otherwise you in a way forcing users of the role add flush\_handlers after the role execution - adn this breaks assumption that roles are “self sufficient”.

Pattern used in this example (with skip if not changed) is much more robust and clear, from my point of view, - you only force changes you know you caused. Here with reboot this might be a bit more on the edge because this is a reboot, but CVE is forcing (I suppose).

My conclusion is that handlers should not be used in the roles, but only in playbooks. This is of course if you do not want users of your role to manually flush\_handlers (which might be good in some cases, like if reboot is handled this way).

What are schools thoughts are there on this topic?

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [April 30, 2026, 3:29pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/4 "2026-04-30T15:29:18Z")

</div>

you don’t NEED to use `flush_handlers` it is there for when you want an ‘early’ trigger. I use roles that only have handlers, to provide them to other roles/plays, sometimes a role has it’s own handlers. For rebooting i have a ‘needs\_reboot’ handler, which lives in a role that also has a couple of tasks that check if a system needs a reboot (kernel change, ubuntu flag file, etc), but i also call from my ‘update packages’ plays.

I pointed at handlers as an option, but I’ll try to be perfectly clear, the `when: x is changed` approach is also fine, use the one that makes more sense in your context.

---

<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:** [April 30, 2026, 4:22pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/5 "2026-04-30T16:22:30Z")

</div>

> [@bcoca](#):
>
> I use roles that only have handlers, to provide them to other roles/plays, sometimes a role has it’s own handlers

That is a nice trick! Thank you for sharing.

> [@bcoca](#):
>
> use the one that makes more sense in your context

… and let the ansible-lint complain about it later )).

> **[no-handler - Ansible Lint Documentation](https://docs.ansible.com/projects/lint/rules/no-handler/)**

This is why I have this question in the first place, this ansible-lint rules looks to me as too restrictive. There are certainly use cases when it does not make sense.

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [April 30, 2026, 4:24pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/6 "2026-04-30T16:24:40Z")

</div>

linting is mostly opinions, sometimes I agree with them, sometimes they are clearly wrong!

---

<div class="post-metadata">

**Author:** ![mariolenz](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mariolenz/32/108_2.png) [@mariolenz](https://forum.ansible.com/u/mariolenz)\
**Post date:** [April 30, 2026, 4:26pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/7 "2026-04-30T16:26:23Z")

</div>

As far as I understand, you’re just making sure that algif\_aead isn’t loaded automatically. But you would have to ensure that it’s not loaded _at all_. The website mentions something like:

> echo “install algif\_aead /bin/false” \> /etc/modprobe.d/disable-algif.conf

This should(?) prevent that the module can be loaded, either by a user or a software having the permissions to do it. If this is done, you’re vulnerable.

Additionally, depending on your distro it might not be a loadable module but built into the kernel. I’ve read somewhere that RHEL did this. In that case, adding `initcall_blacklist=algif_aead_init` or similar to your boot loader should help. Not sure about this, just copy&paste.

Don’t take my word for it, I’ve just had a cursory look at this bug. Please investigate yourself.

---

<div class="post-metadata">

**Author:** ![mariolenz](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/mariolenz/32/108_2.png) [@mariolenz](https://forum.ansible.com/u/mariolenz)\
**Post date:** [April 30, 2026, 4:29pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/8 "2026-04-30T16:29:30Z")

</div>

@kks @bcoca Please move your discussion abound handlers (and linters?) to a dedicated thread. It’s somewhat OT here IMHO.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [April 30, 2026, 5:07pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/9 "2026-04-30T17:07:38Z")

</div>

You are right, sorry I omitted that, I hadn’t realised that any user could load the module, this is what I have updated [the role](https://git.coop/webarch/copyfail/) to use:

```yaml
--- 
- name: Prevent algif_aead kernel module from being loaded
  ansible.builtin.lineinfile:
    path: /etc/modprobe.d/disable-algif.conf
    line: "install algif_aead /bin/false"
    state: present
    create: true
    mode: "0644"
    owner: root
    group: root 
  
- name: Unload algif_aead kernel module
  community.general.modprobe:
    name: algif_aead
    state: absent
    persistent: absent
  register: copyfail_modprobe

- name: Reboot if algif_aead kernel module has been unloaded
  ansible.builtin.reboot:
  when: copyfail_modprobe.changed | ansible.builtin.bool
...

```

Point taken regarding using a handler, I’d forgotten that, but in this case it means the role can consist on just one file…

---

<div class="post-metadata">

**Author:** ![bvitnik](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bvitnik/32/4132_2.png) [@bvitnik](https://forum.ansible.com/u/bvitnik)\
**Post date:** [April 30, 2026, 11:11pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/10 "2026-04-30T23:11:06Z")

</div>

I’m sharing some playbook’s I’ve cooked up today. Maybe they will be of help to someone:

This one tests for vulnerability and makes a CSV report.

```auto
# cve-2026-31431-detect.yml
---
- hosts: os_linux
  gather_facts: true

  tasks:
  - name: Detect CVE-2026-31431
    shell: |-
      import socket

      AF_ALG = 38

      try:
          s = socket.socket(AF_ALG, socket.SOCK_SEQPACKET, 0)
          s.bind(("aead", "gcm(aes)"))
          print("AF_ALG AEAD is available")
      except Exception as e:
          print("AF_ALG AEAD is not available: %s" % e)
    args:
      executable: "{{ ansible_facts['python']['executable'] }}"
    register: result
    changed_when: false
    # failed_when: result['stdout'] == 'AF_ALG AEAD is available'
    # no_log: True

  - name: Set result
    set_fact:
      cve_status: "{{ result['stdout'] == 'AF_ALG AEAD is available' }}"

- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
  - name: Report
    copy:
      dest: "cve-2026-31431-report.csv"
      content: |-
        Machine, Vulnerable, OS
        {% for host in hostvars %}
        {% if host != 'localhost' and 'cve_status' in hostvars[host] %}
        {{ host }}, {{ hostvars[host]['cve_status'] }}, {{ hostvars[host]['ansible_facts']['distribution'] }} {{ hostvars[host]['ansible_facts']['distribution_version'] }}
        {% endif %}
        {% endfor %}

```

This one does a workaround for Ubuntu and RHEL based systems:

```auto
# cve-2026-31431-patch.yml
---
- hosts: os_ubuntu
  gather_facts: false

  tasks:
  - name: Patch CVE-2026-31431
    shell: |-
      echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
      rmmod algif_aead 2>/dev/null || true
    args:
      executable: "/bin/bash"

- hosts: os_rhel_family
  gather_facts: false

  tasks:
  - name: Patch CVE-2026-31431
    shell: |-
      grubby --update-kernel=ALL --args="initcall_blacklist=algif_aead_init"
    args:
      executable: "/bin/bash"

- hosts: os_rhel_8,os_ol_8,os_rocky_8
  gather_facts: false

  tasks:
  - name: Call grub2-mkconfig
    shell: |-
      grub2-mkconfig -o /boot/grub2/grub.cfg
    args:
      executable: "/bin/bash"

```

I tend to use bash instead of native Ansible approach (modules) to speed things a little bit because we are always dealing with thousands of machines. Also, no restart because we have to do it manually in planned maintenance windows.

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [May 2, 2026, 3:20pm UTC](https://forum.ansible.com/t/using-ansible-to-mitigate-copy-fail/45755/11 "2026-05-02T15:20:44Z")

</div>

@bvitnik used your play/script as a base, started doing mitigation for my homelab, though 1/2 my targets didn’t see to need it since i run very stripped down kernels.

> <https://github.com/bcoca/misc-collection/blob/devel/playbooks/cve_2026_31431_copy.fail.yml>

There are a few ansible based cve management frameworks that i’m thinking of porting this to, but for now trying to make it self contained
