T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/init_project.sh:7
- Finding
- Project Name Injection Enables Arbitrary Command Execution and Filesystem Writes<![CDATA[ ## Vulnerability Details **File Location**: `scripts/init_project.sh`, lines 7–17 **Vulnerability Type**: Command injection and path traversal through an unvalidated project name **Risk Level**: High ### Vulnerable Code ```bash PROJECT_NAME=${1:-my-miniprogram} PROJECT_DIR="../${PROJECT_NAME}" echo "📦 正在创建项目: $PROJECT_NAME" # 复制模板 cp -r ../assets/project-template "$PROJECT_DIR" cd "$PROJECT_DIR" # 替换占位符 sed -i "s/{{projectName}}/$PROJECT_NAME/g" package.json taro.config.js config/index.js project.config.json app.config.js project.config.json 2>/dev/null || true ``` ### Technical Analysis The first command-line argument is accepted as `PROJECT_NAME` without validation or escaping. The same untrusted value is used in two security-sensitive contexts: 1. It becomes part of `PROJECT_DIR`, allowing path separators and `..` components to influence where the template is copied. 2. It is interpolated directly into a GNU `sed` program inside a double-quoted shell string. Shell quoting does not make the value safe for the `sed` language. An argument containing `/`, a newline, or other `sed` metacharacters can terminate the intended substitution and introduce additional `sed` commands. GNU `sed` supports the `e` command, which executes an operating-system command. For example, an attacker capable of controlling the script argument and preparing the required parent directory can use a value structurally equivalent to: ```bash $'safe/g\ne touch PWNED\n#' ``` This can transform the generated `sed` program into commands equivalent to: ```sed s/{{projectName}}/safe/g e touch PWNED #/g ``` The injected `e touch PWNED` command is then executed with the privileges of the user running the initialization script. The path construction is independently unsafe. Values containing `../` or path separators can direct `cp -r` outside the expected project-output location. Quoting prevents shell word splitting but does not prevent path traversal. The trailing `|| tr ...[truncated 1571 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce a strict allowlist for project names before using the value: ```bash PROJECT_NAME=${1:-my-miniprogram} if [[ ! "$PROJECT_NAME" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ ]]; then echo "Invalid project name" >&2 exit 1 fi if [[ "$PROJECT_NAME" == "." || "$PROJECT_NAME" == ".." ]]; then echo "Invalid project name" >&2 exit 1 fi ``` 2. Reject all path separators, traversal components, control characters, and newlines. 3. Resolve the destination to a canonical path and verify that it remains below an explicitly approved output directory. 4. Do not generate an executable `sed` program using untrusted text. Use a small Node.js or Python script that reads files as data and performs literal string replacement. 5. If `sed` must be retained, escape replacement metacharacters such as `\`, `/`, and `&`; strict input validation should still be applied. 6. Fail closed when replacement fails. Remove `2>/dev/null || true` and report partial initialization errors. 7. Refuse to overwrite existing destinations unless the user explicitly approves the operation. 8. Run the script with ordinary user privileges and in a restricted workspace, particularly in CI environments. ]]>
