From 8def5bf46ed443ea53d1a7bbb2f9faa8772ecdee Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 18:31:52 +0200 Subject: [PATCH] [PR #11850/f8869af6 backport][stable-12] homebrew_cask: fix sudo_password failing with special characters (#11867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit homebrew_cask: fix sudo_password failing with special characters (#11850) * homebrew_cask: fix sudo_password with special characters in password The SUDO_ASKPASS script embedded the password inside single quotes, which breaks shell parsing whenever the password contains a single quote. Use a quoted heredoc (cat <<'SUDO_PASS') instead, which treats the content completely literally regardless of special characters. Also replace .file.close() with .flush() (correct semantics — flushes the write buffer without leaving the NamedTemporaryFile in a half-closed state) and remove the redundant add_cleanup_file() call (the context manager already deletes the file on exit). Fixes #4957 * homebrew_cask: add changelog fragment for #11850 * homebrew_cask: fix sudo_password example and clarify ansible_become_password * homebrew_cask: use shlex.quote() for sudo_password instead of heredoc shlex.quote() is the standard Python approach for shell-safe quoting and handles all special characters without the edge cases of heredocs. --------- (cherry picked from commit f8869af65f3a4836fb9994f085a0c541b2c4eb1a) Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 --- .../fragments/11850-homebrew-cask-sudo-password.yml | 5 +++++ plugins/modules/homebrew_cask.py | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 changelogs/fragments/11850-homebrew-cask-sudo-password.yml diff --git a/changelogs/fragments/11850-homebrew-cask-sudo-password.yml b/changelogs/fragments/11850-homebrew-cask-sudo-password.yml new file mode 100644 index 0000000000..a4527645e7 --- /dev/null +++ b/changelogs/fragments/11850-homebrew-cask-sudo-password.yml @@ -0,0 +1,5 @@ +bugfixes: + - homebrew_cask - fix ``sudo_password`` failing when the password contains single quotes or + other special shell characters + (https://github.com/ansible-collections/community.general/issues/4957, + https://github.com/ansible-collections/community.general/pull/11850). diff --git a/plugins/modules/homebrew_cask.py b/plugins/modules/homebrew_cask.py index 7729c8c1bd..17020768cb 100644 --- a/plugins/modules/homebrew_cask.py +++ b/plugins/modules/homebrew_cask.py @@ -141,14 +141,16 @@ EXAMPLES = r""" greedy: true - name: Using sudo password for installing cask + # ansible_become_password must be set in inventory or group_vars; it is not populated by -K community.general.homebrew_cask: name: wireshark state: present - sudo_password: "{{ ansible_become_pass }}" + sudo_password: "{{ ansible_become_password }}" """ import os import re +import shlex import tempfile from ansible.module_utils.basic import AnsibleModule @@ -476,14 +478,12 @@ class HomebrewCask: rc, out, err = "", "", "" with tempfile.NamedTemporaryFile() as sudo_askpass_file: - sudo_askpass_file.write(b"#!/bin/sh\n\necho '%s'\n" % to_bytes(self.sudo_password)) + sudo_askpass_file.write(to_bytes(f"#!/bin/sh\necho {shlex.quote(self.sudo_password)}\n")) + sudo_askpass_file.flush() os.chmod(sudo_askpass_file.name, 0o700) - sudo_askpass_file.file.close() rc, out, err = self.module.run_command(cmd, environ_update={"SUDO_ASKPASS": sudo_askpass_file.name}) - self.module.add_cleanup_file(sudo_askpass_file.name) - return (rc, out, err) # /sudo_password fix --------------------- }}}