Description
When sending a live command via lean live command <project> --data <payload>, the command silently fails on Linux if the JSON payload contains the $type key.
The issue occurs because lean-cli uses subprocess.run(..., shell=True) with double quotes ("...") to execute the docker exec command writing the payload to the container. On Unix-like systems, the host shell (/bin/sh) evaluates $type as an environment variable before passing the command to Docker, replacing it with an empty string.
Steps to Reproduce
- On a Linux or macOS machine, run a live algorithm in a Docker container.
- Attempt to send a command requiring the
$type property:
lean live command MyProject --data '{"$type": "MyCustomCommand", "Quantity": 10}'
- The command will fail. The algorithm logs will show it received an invalid command (e.g.,
{"": "MyCustomCommand", "Quantity": 10} because $type evaluated to empty).
Technical Details & Root Cause
In lean.components.docker.docker_manager.py:write_to_file(), the command is constructed as follows:
data = dumps(data, cls=DecimalEncoder)
data = data.replace('"','\\"')
command = f'docker exec {docker_container_name} bash -c "echo \'{data}\' > {docker_file.as_posix()}"'
try:
run(command, shell=True, check=True)
- The
--data argument is evaluated and dumped back into a JSON string using json.dumps().
- All double quotes
" are replaced with \".
- The command string wraps the
echo statement inside double quotes (bash -c "echo ...") and executes it via shell=True.
Because json.dumps() guarantees an even number of backslashes, passing \$type via the terminal doesn't work (Python parses the backslash out, or dumps adds a second one \\$type). Consequently, the host's /bin/sh sees "$type" unescaped and expands it.
(Note: This bug does not affect Windows, as cmd.exe does not use the $ syntax for environment variables).
Description
When sending a live command via
lean live command <project> --data <payload>, the command silently fails on Linux if the JSON payload contains the$typekey.The issue occurs because
lean-cliusessubprocess.run(..., shell=True)with double quotes ("...") to execute thedocker execcommand writing the payload to the container. On Unix-like systems, the host shell (/bin/sh) evaluates$typeas an environment variable before passing the command to Docker, replacing it with an empty string.Steps to Reproduce
$typeproperty:{"": "MyCustomCommand", "Quantity": 10}because$typeevaluated to empty).Technical Details & Root Cause
In
lean.components.docker.docker_manager.py:write_to_file(), the command is constructed as follows:--dataargument is evaluated and dumped back into a JSON string usingjson.dumps()."are replaced with\".echostatement inside double quotes (bash -c "echo ...") and executes it viashell=True.Because
json.dumps()guarantees an even number of backslashes, passing\$typevia the terminal doesn't work (Python parses the backslash out, ordumpsadds a second one\\$type). Consequently, the host's/bin/shsees"$type"unescaped and expands it.(Note: This bug does not affect Windows, as
cmd.exedoes not use the$syntax for environment variables).