T09 · Insecure Skill Coding Practices
- Location
scripts/manage_local_claw_skill_nest.ts:95- Finding
PowerShell Command Injection Through an Unvalidated Skill Name
- Content
View full analysis
{ try { if (process.platform === 'win32') { await run('powershell', [ '-NoProfile', '-Command', `Expand-Archive -Path \"${archivePath}\" -DestinationPath \"${targetDir}\" -Force`, ]); return true; } ``` The affected destination is constructed from the externally influenced Skill name: ```ts const skillDir = join(SKILLS_DIR, skillName); ``` ### Technical Analysis On Windows, `targetDir` is interpolated directly into a string passed to PowerShell's `-Command` argument. The backslashes before the double quotes are JavaScript string escapes; they do not provide PowerShell-safe escaping in the resulting command. The `targetDir` value includes `skillName`. The name is supplied through a command-line argument and must also match a name returned by the configured repository. A malicious or compromised repository can publish a specially crafted name containing a quotation mark and PowerShell syntax. If that name is selected for installation, the injected syntax becomes part of the PowerShell program. Using `spawn()` does not prevent this vulnerability because PowerShell is intentionally invoked with `-Command`, causing the supplied string to be interpreted as executable PowerShell source. ### Attack Path 1. An attacker controls or compromises the configured private Skill repository. 2. The repository returns a Skill whose `name` contains PowerShell metacharacters and injected commands. 3. The user installs that Skill using its exact repository-provided name. 4. `installSkill()` incorporates the name into `skillDir`. 5. `extractZip()` interpolates that directory into a PowerShell `-Command` string. 6. PowerShell parses and ...[truncated 423 chars]- Remediation
View remediation
