T09 · Insecure Skill Coding Practices
- Location
SKILL.md:31- Finding
Shell Command Injection Through Unvalidated Publishing Inputs
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 31–46 and 69–91
Vulnerability Type: Shell command injection through unsafe interpolation of user-controlled arguments
Risk Level: HighVulnerable Code
markdown 2. Check required inputs: skill slug, source path, target version, changelog, expected content. 3. Confirm the source path contains SKILL.md. 4. Check for secrets or private credentials before publishing. 5. If updating an existing skill, check the current live version first. 6. Publish with the local ClawHub CLI. 7. Verify the live registry state with `clawhub inspect <slug>`. Common commands: ```bash clawhub publish <path> --version <semver> --changelog "<note>" clawhub inspect <slug>text The copy-paste workflow also accepts the affected fields directly from a request: ```markdown Skill slug: [slug] Source path: [absolute path] Target version: [x.y.z] Changelog: [one specific release note] Rules: - Check that the source path contains SKILL.md. - Check for secrets or private credentials before publishing. - If updating an existing skill, check current live version first via clawhub inspect <slug>. - Publish with the local ClawHub CLI. - Verify with clawhub inspect <slug> after publishing.Technical Analysis
The Skill accepts the slug, source path, target version, and changelog from the user and instructs the Agent to interpolate those values into command-line examples. It does not require structured process invocation, robust shell escaping, or strict validation of shell-sensitive characters.
The source path and slug are shown without quoting. Although the changelog is surrounded by double quotes, an attacker-controlled value can terminate that quoted context or use command substitution where supported. Merely checking that values are present does not establish that they are safe shell arguments.
If an implementation follows these instructions by constructing a command string and passing it to a shell, ...[truncated 1801 chars]
- Remediation
View remediation
Remediation Suggestions
-
Prohibit shell-string execution. Require invocation of a fixed executable using an argument array, such as the conceptual equivalent of:
text execFile("clawhub", [ "publish", validatedPath, "--version", validatedVersion, "--changelog", changelog ])Do not use
shell=True,sh -c,bash -c,eval, or concatenated command strings. -
Strictly validate slugs. Apply a conservative allowlist such as:
regex ^[a-z0-9]+(?:-[a-z0-9]+)*$Also enforce documented namespace restrictions and reject control characters, whitespace, path separators, and shell metacharacters.
-
Parse versions structurally. Use a SemVer parser and reject any value that is not exactly a valid semantic version. Pass the normalized result as one process argument.
-
Constrain source paths. Resolve the path canonically, verify that it is an existing directory containing
SKILL.md, and require it to reside under an approved skill root or match an explicit canonical override. Reject null bytes, control characters, and ambiguous traversal. -
Treat changelogs as literal data. Permit normal prose but reject control characters and unexpected newlines where unnecessary. Always pass the entire changelog as one argument without shell interpretation.
-
Update the Skill instructions. Explicitly state that all request fields are untrusted and must never be interpolated into a shell command. Replace copy-paste shell templates with structured tool-call examples or clearly marked placeholders accompanied by mandatory validation rules.
-
Apply least privilege. Run publishing operations under a dedicated, non-root account with access limited to approved source directories and required ClawHub credentials.
-
