Skip to content

Agent extension installer joins untrusted skill/plugin names and archive members without containing them

agent-extension-install-path-containment is a high severity check in the ai category, written in shell. Its source is templates/ai/coding-agent/agent-extension-install-path-containment.sh in cert-x-gen-templates.

Drives an agent CLI’s own install verb, inside a throwaway $HOME, against three benign synthetic extensions whose only unusual property is the NAME an attacker controls - a skill whose SKILL.md frontmatter name is ../../<nonce>, a plugin manifest whose name is ../../../.ssh, and a .tar pack carrying a symlink to $HOME/.ssh/authorized_keys followed by a member written through it. Each install is preceded by a benign-named control install of the same shape, which is what resolves the tool’s real skills/plugins/packs root; the probe then asks one question of the filesystem - did this arm’s nonce land outside that resolved root, or was a link that leaves it followed or preserved. Confirms only on an observed escape, refutes when every arm was rejected or normalised in place, and skips when the target exposes no install verb (SkillSlip / extension-installer containment class).

Field Value
Id agent-extension-install-path-containment
Severity high
Language shell
Category ai
Author CERT-X-GEN Security Team
Template version not recorded
Confidence 92
CVSS not recorded
Weakness CWE-22
Tags ai, coding-agent, cli, skills, plugins, marketplace, install, path-traversal, zip-slip, symlink, containment, cwe-22, cwe-23, cwe-59, cwe-829
Target kind cli
Oracle property

Declared in the header. cxg parses @references and then discards it, and nothing at scan time reads it, so this is the only place the links a template cites are surfaced.

To see what the copy on your machine says about itself, and to confirm it is installed at all:

Terminal window
cxg template info agent-extension-install-path-containment

The id it prints is the one to pass anywhere a template is selected. See cxg template for the rest of the subcommand, Scan a target for running a scan, and A match is not a finding for how to read what comes back.