T09 · Insecure Skill Coding Practices
- Location
SKILL.md:105- Finding
Unvalidated Topic Slug Can Reach Filesystem Paths and Shell Commands
- Content
View full analysis
Vulnerability Details
File Locations:
SKILL.md:105-106SKILL.md:201-204SKILL.md:217-223
Vulnerability Type: Command injection, path traversal, option injection, and unsafe temporary-file handling
Risk Level: HighVulnerable Code
markdown | `topic_slug` | 从 topic 派生 | 转为适合文件命名和 name 字段的格式(小写、下划线、无空格,如 "distributed_systems") | | `project_dir` | 从 topic_slug 派生 | `learn_` + topic_slug + `/`(如 `learn_distributed_systems/`),项目文件的存放目录 |markdown 1. 在当前工作空间内,按探测到的 `{skill_prefix}` 创建 skill 目录:`{skill_prefix}/learn_{{topic_slug}}/` 2. 将生成的 SKILL.md 写入该目录 3. 在该目录下创建 `references/` 子目录,写入 review_guide.md 和 framework_guide.md 4. 在当前工作空间根目录下创建项目文件目录 `learn_{{topic_slug}}/`markdown 1. 在 /tmp/ 下创建临时目录 `learn_{{topic_slug}}_package/` 2. 在临时目录内按探测到的 `{skill_prefix}` 创建 skill 目录结构:`{skill_prefix}/learn_{{topic_slug}}/SKILL.md` + `{skill_prefix}/learn_{{topic_slug}}/references/` 3. 在临时目录内创建项目文件目录:`learn_{{topic_slug}}/` 4. 写入所有文件(同路径1步骤2-3)。同样使用文件写入工具,避免 Shell heredoc 5. 执行 zip 打包:`cd /tmp && zip -r learn_{{topic_slug}}.zip learn_{{topic_slug}}_package/` 6. 将 zip 文件移动到用户工作目录 7. 清理临时目录Technical Analysis
The user-controlled learning topic is converted into
topic_slug, which is subsequently interpolated into directory names, archive names, a predictable/tmpdirectory, and a Bash command. Although the instructions describe the desired slug as lowercase, underscore-separated, and without spaces, they do not define or enforce a strict character allowlist.In particular, the Skill does not explicitly require the implementation to:
- Reject path separators such as
/or\. - Reject parent-directory components such as
... - Reject shell metacharacters and command substitutions.
- Reject leading hyphens that may be interpreted as command-line options.
- Enforce a maximum slug length.
- Canonicalize generated paths an ...[truncated 3250 chars]
- Remediation
View remediation
Remediation Suggestions
-
Define and enforce a strict slug allowlist. Require
topic_slugto match a narrow expression such as^[a-z0-9_]{1,64}$. Reject invalid values instead of attempting to preserve or loosely normalize dangerous input. -
Use a trusted slugification routine. Convert the topic to normalized Unicode, transliterate where appropriate, lowercase it, replace separators with a single underscore, and remove every character outside the allowlist. Validate the final result again before use.
-
Prevent path traversal. Resolve each destination to a canonical absolute path and verify that it remains beneath the approved workspace or temporary root before creating or writing files.
-
Avoid interpolated shell commands. Invoke ZIP through a structured process API with a fixed executable and separate argument array. If Bash is unavoidable, apply robust shell quoting to every variable and use
--before user-derived positional arguments where supported. -
Use secure temporary directories. Create a unique temporary directory through a secure facility such as
mktemp -d, apply restrictive permissions, avoid following symlinks, and clean it up in a guaranteed finalization step. -
Reject option-like names. Do not permit generated filenames or directory names to begin with
-, even if a downstream command uses--. -
Limit filesystem scope. Permit writes only beneath the selected Skill installation directory, project directory, and securely created temporary directory. Abort delivery if any resolved path escapes those roots.
-
Document validation as a mandatory security requirement. Add explicit validation and containment checks to the generation checklist so that Agents cannot interpret the current examples as merely advisory formatting guidance.
-
