T09 · Insecure Skill Coding Practices
Error
- Location
- publish.sh:28
- Finding
- Shell Command Injection in the Publishing Script## Vulnerability Details **File Location**: `publish.sh`, lines 28-29 and 87-92 **Vulnerability Type**: Shell command injection through unsafe use of `eval` **Risk Level**: High ### Vulnerable 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"; then ``` ### Technical Analysis The script accepts `VERSION` and `CHANGELOG` from its first and second positional arguments. It interpolates these values into a command string and executes that string with `eval`. Unlike direct command invocation, `eval` causes 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 `$CHANGELOG` inside 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. `$VERSION` is interpolated without even attempted quoting. ### Attack Path 1. An attacker supplies or persuades a maintainer to use a crafted version or changelog argument. 2. The maintainer runs `publish.sh` in the project directory. 3. The script assigns the attacker-controlled value to `VERSION` or `CHANGELOG`. 4. The value is inserted into `PUBLISH_CMD`. 5. `eval "$PUBLISH_CMD"` reparses the resulting text as shell code. 6. 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
- ## Remediation Suggestions Remove the command string and `eval`. Invoke `clawhub` directly, 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 fi ``` Apply 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 fi ``` Additional hardening measures: 1. Treat changelog content exclusively as data and never pass it through `eval`, `bash -c`, or another shell interpreter. 2. Avoid printing sensitive command-line content if future changelogs or options could contain confidential information. 3. Run publication from a minimally privileged account with narrowly scoped ClawHub credentials. 4. Add regression tests using arguments containing spaces, quotation marks, semicolons, command substitutions, and redirection operators to confirm they remain literal data. 5. Refactor the generic `eval` use in `validate.sh` as defense in depth, even though the currently observed callers use fixed internal command strings.
