T09 · Insecure Skill Coding Practices
- Location
publish.sh:28- Finding
Shell Command Injection in the Publishing Script
- Content
View full analysis
Vulnerability Details
File Location:
publish.sh, lines 28-29 and 87-92
Vulnerability Type: Shell command injection through unsafe use ofeval
Risk Level: HighVulnerable Code
bash VERSION=${1:-$(jq -r '.version' skill.json)} CHANGELOG=${2:-"See CHANGELOG.md for details"}bash PUBLISH_CMD="clawhub publish $SCRIPT_DIR --slug family-steward --version $VERSION --changelog \"$CHANGELOG\"" echo " Command: $PUBLISH_CMD" echo "" if eval "$PUBLISH_CMD"; thenTechnical Analysis
The script accepts
VERSIONandCHANGELOGfrom its first and second positional arguments. It interpolates these values into a command string and executes that string witheval.Unlike direct command invocation,
evalcauses the fully constructed string to be parsed again by the shell. Consequently, shell syntax embedded in either user-controlled argument—including command separators, redirections, pipelines, or command substitutions—can be interpreted as executable syntax rather than as literal argument data.Quoting
$CHANGELOGinside the constructed string is insufficient because an attacker can inject quotation marks or other shell syntax that changes the command structure during the second parsing pass.$VERSIONis interpolated without even attempted quoting.Attack Path
- An attacker supplies or persuades a maintainer to use a crafted version or changelog argument.
- The maintainer runs
publish.shin the project directory. - The script assigns the attacker-controlled value to
VERSIONorCHANGELOG. - The value is inserted into
PUBLISH_CMD. eval "$PUBLISH_CMD"reparses the resulting text as shell code.- The injected shell command executes under the maintainer's operating-system account.
For example, a malicious version argument can introduce a command separator followed by an arbitrary command. The precise payload does not require modification of the script or the project metadata.
Impact Assessment
Suc ...[truncated 862 chars]
- Remediation
View remediation
Remediation Suggestions
Remove the command string and
eval. Invokeclawhubdirectly, passing each value as a separately quoted argument:bash if clawhub publish "$SCRIPT_DIR" \ --slug family-steward \ --version "$VERSION" \ --changelog "$CHANGELOG"; then echo "" echo -e "${GREEN}✅ Successfully published to ClawHub!${NC}" else echo "" echo -e "${RED}❌ Publishing failed${NC}" exit 1 fiApply a strict allowlist to the version argument before invoking the publishing command. For example:
bash if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]]; then echo "Invalid semantic version" >&2 exit 1 fiAdditional hardening measures:
- Treat changelog content exclusively as data and never pass it through
eval,bash -c, or another shell interpreter. - Avoid printing sensitive command-line content if future changelogs or options could contain confidential information.
- Run publication from a minimally privileged account with narrowly scoped ClawHub credentials.
- Add regression tests using arguments containing spaces, quotation marks, semicolons, command substitutions, and redirection operators to confirm they remain literal data.
- Refactor the generic
evaluse invalidate.shas defense in depth, even though the currently observed callers use fixed internal command strings.
- Treat changelog content exclusively as data and never pass it through
