T09 · Insecure Skill Coding Practices
Error
- Location
- references/config-center-template.md:10
- Finding
- Unvalidated Template Interpolation Enables Kotlin Source-Code Injection<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:48-49`; `references/api-template.md:43`; `references/config-center-template.md:10-13`; `references/push-pull-template.md:10-11`; `references/whitelist-template.md:9` **Vulnerability Type**: Source-code injection through unsafe template interpolation **Risk Level**: High The Skill requires generated code to be written into the user's workspace: ```markdown - 代码优先使用 Kotlin 编写 - 数据模型如果跟网络相关需要添加 `@Keep` 注解 - **生成代码后,必须写入到 workspace 对应文件,并展示给用户看** ``` Multiple user-controlled values are inserted directly into Kotlin source-code templates without escaping, validation, or identifier normalization. `references/api-template.md:43`: ```kotlin public interface {Name}Service { @POST("{apiUrl}") Observable<{Name}Response> query{Name}Config(@Body {Name}Request request); } ``` `references/config-center-template.md:10-13`: ```kotlin private const val CONFIG_KEY_CONFIG_VERSION = "1.0.0" private const val CONFIG_KEY_YZ_HD_{NAME}_CONFIG = "{componentKey}" private const val TAG = "{Name}ConfigManager" private const val CONFIG_KEY_YZ_HD_{NAME}_CONFIG_KEY = "{fieldKey}" ``` `references/push-pull-template.md:10-11`: ```kotlin private const val PUSH_KEY = "{pushKey}" private const val PULL_URL = "{pullUrl}" ``` `references/whitelist-template.md:9`: ```kotlin WhiteListTask.isInWhiteList({key}).subscribe({ result -> // TODO 待实现 }, { error -> // TODO 待实现 }) ``` ### Technical Analysis The placeholders include configuration names, JSON-derived field names, API URLs, component keys, field keys, push keys, pull URLs, and whitelist keys. These values can enter either: 1. **Kotlin string-literal contexts**, such as `"{componentKey}"` and `"{pullUrl}"`; or 2. **Kotlin identifier contexts**, such as `{Name}`, `{NAME}`, method names, class names, and generated JSON property names. No instruction requires escaping Kotlin string literals, rejecting line breaks or control characters, validating identifiers ...[truncated 2393 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Validate generated identifiers** - Permit identifiers only when they match a strict pattern such as `^[A-Za-z_][A-Za-z0-9_]*$`. - Apply the same validation after capitalization, case conversion, or other name transformations. - Reject Kotlin and Java reserved words or map them to explicitly safe alternatives. - Never derive declarations directly from arbitrary JSON property names. 2. **Escape string literals with a dedicated encoder** - Encode quotation marks, backslashes, carriage returns, line feeds, tabs, Unicode separators, and control characters before inserting values into Kotlin or Java literals. - Do not rely on manual replacement or Markdown formatting. - Prefer a tested code-generation library that builds language syntax trees rather than concatenating strings. 3. **Validate keys and URLs** - Define restrictive character and length allowlists for component, field, push, and whitelist keys. - Parse URLs or API paths before generation. - Permit only expected schemes, hosts, path formats, and API versions. - Reject embedded whitespace, comments, quotation marks, newlines, and delimiter characters. 4. **Validate template JSON** - Parse supplied JSON with a strict parser. - Enforce an explicit schema, nesting-depth limit, field-count limit, and maximum input size. - Map JSON properties to safe generated identifiers rather than using property names verbatim. - Reject unsupported property types and duplicate or ambiguous normalized names. 5. **Introduce a safe write workflow** - Generate files in memory first. - Present an exact diff and destination paths to the user. - Require explicit confirmation before modifying existing workspace files. - Prevent path traversal and ensure every destination remains under the intended module directory. - Avoid silently overwriting existing managers or plugin modules. 6. **Add adversarial tests** - Test inputs containi ...[truncated 302 chars]
