T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/main.py:139
- Finding
- Arbitrary Python Code Injection in Generated Presentation Script## Vulnerability Details **File Location**: `scripts/main.py`, lines 139-143 **Vulnerability Type**: Python source-code injection through unescaped string interpolation **Risk Level**: High ### Vulnerable Code ```python title.text = "{content.get('title', 'Title')}" subtitle.text = "Generated Presentation" # Save presentation prs.save('{output_file}') print(f"Created: {output_file}") ``` The interpolated title originates from the first line of a user-supplied abstract file: ```python content = { "title": lines[0] if lines else "Untitled", "background": "", "methods": "", "results": "", "conclusion": "" } ``` The output filename is also accepted directly from the command line: ```python parser.add_argument("--output", "-o", default="output.pptx", help="Output file") ``` The affected generator is invoked and its result is written as executable Python at lines 184-189: ```python if args.generate_code: code = generator.generate_python_pptx_code(content, args.format, args.output) code_file = args.output.replace(".pptx", "_generator.py") with open(code_file, 'w') as f: f.write(code) print(f"\nGenerator code saved to: {code_file}") ``` ### Technical Analysis `generate_python_pptx_code()` constructs Python source with an f-string. It places `content["title"]` inside a double-quoted Python string literal and `output_file` inside a single-quoted Python string literal without applying Python-literal escaping. An attacker can supply quote characters, newlines, backslashes, or statements that terminate the intended string literal and introduce arbitrary Python syntax. The resulting file is treated as a normal Python generator script. This is a second-stage vulnerability: generating the file does not itself execute the injected payload, but execution occurs if the user or an automated workflow subsequently runs that generated script. Both input channels are affected: 1. The first line of the file supplied through `--a ...[truncated 1482 chars]
- Remediation
- ## Remediation Suggestions Serialize every dynamic value as a valid Python literal rather than placing raw data between manually written quotation marks. For example: ```python safe_title = repr(content.get("title", "Title")) safe_output = repr(str(output_file)) code = f'''#!/usr/bin/env python3 from pptx import Presentation prs = Presentation() title_slide_layout = prs.slide_layouts[0] slide = prs.slides.add_slide(title_slide_layout) title = slide.shapes.title subtitle = slide.placeholders[1] title.text = {safe_title} subtitle.text = "Generated Presentation" prs.save({safe_output}) print("Presentation created") ''' ``` The `!r` conversion may also be applied directly: ```python title.text = {content.get("title", "Title")!r} prs.save({str(output_file)!r}) ``` Additional hardening measures should include: 1. Prefer creating the PowerPoint directly in the trusted application instead of emitting executable Python source. 2. If source generation must remain supported, build an abstract syntax tree and serialize it with trusted Python tooling rather than using an f-string source template. 3. Treat generated scripts as untrusted artifacts and do not execute them automatically. 4. Validate output paths according to the intended deployment boundary and prevent writes outside an approved output directory where applicable. 5. Add regression tests for titles and paths containing single quotes, double quotes, backslashes, newlines, semicolons, comment characters, and attempted statement injection. 6. Verify that crafted inputs remain inert data in the generated program and cannot alter its syntax.
