From 865c96e66c2d76b53526596c8cf230ed0db66150 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 18:31:36 +0200 Subject: [PATCH] [PR #11850/f8869af6 backport][stable-11] homebrew_cask: fix sudo_password failing with special characters (#11866) 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 Co-Authored-By: Claude Sonnet 4.6 * homebrew_cask: add changelog fragment for #11850 Co-Authored-By: Claude Sonnet 4.6 * homebrew_cask: fix sudo_password example and clarify ansible_become_password Co-Authored-By: Claude Sonnet 4.6 * 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. Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 (cherry picked from commit f8869af65f3a4836fb9994f085a0c541b2c4eb1a) * Make Python 2 compatible. --------- Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Felix Fontein --- .../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 948f5c1fd1..ea4f4d3683 100644 --- a/plugins/modules/homebrew_cask.py +++ b/plugins/modules/homebrew_cask.py @@ -145,14 +145,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_collections.community.general.plugins.module_utils.version import LooseVersion @@ -469,17 +471,15 @@ class HomebrewCask(object): 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(b"#!/bin/sh\necho %s\n" % to_bytes(shlex.quote(self.sudo_password))) + 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 --------------------- }}}