T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:139- Finding
Arbitrary Python Code Injection in Generated Presentation Script
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py, lines 139-143
Vulnerability Type: Python source-code injection through unescaped string interpolation
Risk Level: HighVulnerable 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 placescontent["title"]inside a double-quoted Python string literal andoutput_fileinside 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:
- The first line of the file supplied through `--a ...[truncated 1482 chars]
- Remediation
View 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
!rconversion may also be applied directly:python title.text = {content.get("title", "Title")!r} prs.save({str(output_file)!r})Additional hardening measures should include:
- Prefer creating the PowerPoint directly in the trusted application instead of emitting executable Python source.
- 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.
- Treat generated scripts as untrusted artifacts and do not execute them automatically.
- Validate output paths according to the intended deployment boundary and prevent writes outside an approved output directory where applicable.
- Add regression tests for titles and paths containing single quotes, double quotes, backslashes, newlines, semicolons, comment characters, and attempted statement injection.
- Verify that crafted inputs remain inert data in the generated program and cannot alter its syntax.
