T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/export.py:421
- Finding
- Untrusted Skill Metadata Can Inject Python Code into the Generated Service<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export.py:280-287, 421-426` **Vulnerability Type**: Untrusted data interpolation into generated source code **Risk Level**: High ### Vulnerable Code ```python name = name_match.group(1).strip() if name_match else skill_path.name description = desc_match.group(1).strip() if desc_match else "Exported skill service" return { "name": name, "description": description, "content": content } ``` ```python api_content = TEMPLATES["api.py"].format( skill_name=skill_info["name"], skill_description=skill_info["description"], endpoints=endpoints ) (output_path / "api.py").write_text(api_content) ``` The affected template inserts these values directly into Python string literals: ```python app = FastAPI( title="{skill_name} API", description="{skill_description}", version="1.0.0" ) ``` ### Technical Analysis The `name` and `description` fields are extracted from a source Skill's `SKILL.md` frontmatter using regular expressions. Their contents are not parsed with a structured YAML parser, constrained to a safe character set, or encoded as Python string literals before being inserted into the generated `api.py`. An attacker-controlled value containing quotation marks, newlines, and Python syntax can terminate the intended string literal and introduce arbitrary Python statements. The resulting payload executes when the generated application imports `api.py`, including when Uvicorn starts the exported service. This is a source-code generation injection vulnerability. Merely using `str.format()` does not escape data for the Python syntax context in which it is inserted. ### Attack Path 1. An attacker creates or supplies a source Skill containing a crafted `SKILL.md`. 2. The frontmatter's `name` or `description` field contains content designed to escape the generated Python string literal. 3. A user invokes the exporter with the malicious Skill as `--skill`. 4. `parse_sk ...[truncated 1134 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse frontmatter with a maintained YAML parser rather than regular expressions. 2. Validate the Skill name against a strict allowlist suitable for service names, such as: ```python if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_-]{0,63}", name): raise ValueError("Invalid skill name") ``` 3. Encode metadata as valid Python literals before template insertion: ```python api_content = TEMPLATES["api.py"].format( skill_name_literal=repr(skill_info["name"]), skill_description_literal=repr(skill_info["description"]), endpoints=endpoints, ) ``` The template should use the literals without adding another pair of quotation marks: ```python app = FastAPI( title={skill_name_literal}, description={skill_description_literal}, version="1.0.0" ) ``` 4. Prefer generating a separate JSON metadata file and loading it at runtime rather than embedding untrusted metadata in executable source code. 5. Compile the generated file with `python -m py_compile api.py` before reporting a successful export. 6. Add regression tests containing quotes, backslashes, multiline values, braces, and attempted Python statements. ]]>
