The sudo password doesn't seem to be properly escaped
Describe the bug
A sudo password containing a semicolon (;) is and read correctly. The part after the ; is read as another command by the shell.
To Reproduce
With a file demo.py containing:
from pyinfra.operations import server
server.shell("echo zoo", _sudo=True, _sudo_password="asdf;ghjk")
And then running pyinfra -y @local demo.py.
Results in:
--> Loading config...
--> Loading inventory...
--> Connecting to hosts...
[@local] Connected
--> Preparing operations...
--> Preparing Operations...
Loading: demo.py
[@local] Ready: demo.py
--> Skipping change detection
--> Beginning operation run...
--> Starting operation: server.shell (echo zoo)
[@local] >>> env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-rn5Vra4Gl1Ys *** sudo -H -A -k sh -c 'echo zoo'
...[all my env dumped]...
[@local] PYINFRA_SUDO_PASSWORD=asdf
[@local] /bin/sh: line 1: ghjk: command not found
[@local] Error: executed 0 commands
--> Disconnecting from hosts...
--> pyinfra error: No hosts remaining!
-
Operation code & usage Here
serveroperations is used, but I presume it would apply to any operations using the sudo password. -
Target system information Seen on Fedora Linux 38.
-
Example using the
@dockerconnector (helps isolate the problem)
pyinfra -y @docker/d9b8dc0bb6a1 demo.py
--> Loading config...
--> Loading inventory...
--> Connecting to hosts...
[@docker/d9b8dc0bb6a1] Connected
--> Preparing operations...
--> Preparing Operations...
Loading: demo.py
[@docker/d9b8dc0bb6a1] Ready: demo.py
--> Skipping change detection
--> Beginning operation run...
--> Starting operation: server.shell (echo zoo)
[@docker/d9b8dc0bb6a1] HOSTNAME=d9b8dc0bb6a1
[@docker/d9b8dc0bb6a1] HOME=/root
[@docker/d9b8dc0bb6a1] PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[@docker/d9b8dc0bb6a1] PWD=/
[@docker/d9b8dc0bb6a1] SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-zoLJuvakPyox
[@docker/d9b8dc0bb6a1] PYINFRA_SUDO_PASSWORD=asdf
[@docker/d9b8dc0bb6a1] sh: 1: ghjk: not found
[@docker/d9b8dc0bb6a1] Error: executed 0 commands
--> Disconnecting from hosts...
[@docker/d9b8dc0bb6a1] docker build complete, container left running: d9b8dc0bb6a1
--> pyinfra error: No hosts remaining!
Expected behavior
I expect the ; not affecting the use of the sudo password.
Meta
- Include output of
pyinfra --support.
System: Linux
Platform: Linux-6.8.4-100.fc38.x86_64-x86_64-with-glibc2.37
Release: 6.8.4-100.fc38.x86_64
Machine: x86_64
pyinfra: v3.0b1
Executable: /home/felix/.local/bin/pyinfra
Python: 3.11.8 (CPython, GCC 13.2.1 20231011 (Red Hat 13.2.1-4))
-
How was pyinfra installed (source/pip)?
pipx install pyinfra==3.0b1 --force -
Include pyinfra-debug.log (if one was created) There was none.
-
Consider including output with
-vvand--debug.
--> Loading config...
--> Loading inventory...
[pyinfra_cli.inventory] Creating fake inventory...
[pyinfra_cli.inventory] Checking possible group_data directory: /home/felix
--> Connecting to hosts...
[@local] Connected
[pyinfra.api.state] Activating host: @local
--> Preparing operations...
--> Preparing Operations...
Loading: demo.py
[pyinfra.api.operation] Adding operation, {'server.shell'}, opOrder=(0, 3), opHash=cedda09f9ebcba03bb3a36b21a0111fc8b7c3ec0
[@local] Ready: demo.py
--> Skipping change detection
--> Beginning operation run...
--> Starting operation: server.shell (echo zoo)
[pyinfra.api.operations] Starting operation {'server.shell'} on @local
[pyinfra.connectors.local] --> Running command on localhost: sh -c '
temp=$(mktemp "${TMPDIR:=/tmp}/pyinfra-sudo-askpass-XXXXXXXXXXXX")
cat >"$temp"<<'"'"'__EOF__'"'"'
#!/bin/sh
printf '"'"'%s\n'"'"' "$PYINFRA_SUDO_PASSWORD"
__EOF__
chmod 755 "$temp"
echo "$temp"
'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 0
[pyinfra.connectors.local] --> Running command on localhost: env SUDO_ASKPASS=/tmp/pyinfra-sudo-askpass-RNKJiA1Wg1RE *** sudo -H -A -k sh -c 'echo zoo'
[pyinfra.connectors.util] --> Waiting for exit status...
[pyinfra.connectors.util] --> Command exit status: 127
......
[@local] PYINFRA_SUDO_PASSWORD=asdf
[@local] /bin/sh: line 1: ghjk: command not found
[@local] Error: executed 0 commands
[pyinfra.api.state] Failing hosts: @local
--> Disconnecting from hosts...
--> pyinfra error: No hosts remaining!
Thank you very much!
I think this should be fixed by https://github.com/pyinfra-dev/pyinfra/commit/9b6c214effb75b4c485b3766a135bae26029edbd? (not yet released)
This is now fixed in the latest releases per above!