pyinfra icon indicating copy to clipboard operation
pyinfra copied to clipboard

The sudo password doesn't seem to be properly escaped

Open elisium-oat opened this issue 1 year ago • 1 comments

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 server operations 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 @docker connector (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 -vv and --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!

elisium-oat avatar May 12 '24 19:05 elisium-oat

I think this should be fixed by https://github.com/pyinfra-dev/pyinfra/commit/9b6c214effb75b4c485b3766a135bae26029edbd? (not yet released)

sudoBash418 avatar May 13 '24 00:05 sudoBash418

This is now fixed in the latest releases per above!

Fizzadar avatar Aug 04 '24 13:08 Fizzadar