T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/generate_tex_for_assets.py:13
- Finding
- LaTeX Command Injection Through Unsanitized Asset Filenames## Vulnerability Details **File Location**: `scripts/generate_tex_for_assets.py`, lines 13-16 **Vulnerability Type**: LaTeX command injection caused by unsafe generation of source code **Risk Level**: Medium **Vulnerable Code**: ```python def generate_tex(src: Path): dst = src.with_suffix(".tex") if dst.exists(): return code = TEX_FIG.replace("SOURCE", src.as_posix()).replace("NAME", str(src.stem)) dst.write_text(code) print(f"Generated: {dst}") ``` ### Technical Analysis The script recursively processes asset files and directly embeds both `src.as_posix()` and `src.stem` into a LaTeX document template: ```latex \includegraphics[width=0.5\linewidth]{SOURCE} \label{fig:NAME} ``` Neither value is validated against an allowlist nor escaped for LaTeX syntax. On filesystems that permit characters such as backslashes, braces, percent signs, and other TeX metacharacters in filenames, an attacker-controlled asset name can terminate the expected argument and introduce additional LaTeX commands. The vulnerability crosses a trust boundary: a filesystem filename is treated as inert data by Python but subsequently becomes executable source syntax when the generated `.tex` file is compiled. Injection through the `SOURCE` placeholder is particularly dangerous because it occurs inside the `\includegraphics` argument. The filename stem is also independently inserted into `\label`, providing another injection location. The generator does not itself execute LaTeX, so exploitation requires the generated file to be included and compiled. The exact consequences depend on the TeX engine, installed packages, operating-system permissions, and compilation options. ### Attack Path 1. An attacker supplies or modifies a LaTeX project containing a `.png` or `.jpg` asset with LaTeX control characters and commands in its filename. 2. The user follows the documented workflow and runs: ```bash python <ski ...[truncated 1726 chars]
- Remediation
- ## Remediation Suggestions 1. **Apply a strict filename policy before generation.** Reject asset names containing anything outside a conservative allowlist. For example, permit only ASCII letters, digits, periods, underscores, and hyphens. ```python import re SAFE_FILENAME = re.compile(r"^[A-Za-z0-9_.-]+$") if not SAFE_FILENAME.fullmatch(src.name): raise ValueError(f"Unsafe asset filename: {src.name!r}") ``` 2. **Generate labels separately from paths.** Convert the stem to a canonical identifier containing only safe characters rather than inserting the original stem into `\label`. ```python safe_label = re.sub(r"[^A-Za-z0-9_-]", "-", src.stem) ``` 3. **Do not rely only on generic text replacement.** Construct the template using explicitly validated values so each insertion point has a documented security policy. 4. **Normalize and constrain discovered files.** Resolve each source path and verify that it remains under the intended `assets` directory before writing output. 5. **Use restrictive LaTeX compilation settings.** Disable shell escape, use a sandboxed build environment, limit filesystem access, and compile untrusted projects under a dedicated low-privilege account. These controls provide defense in depth if unsafe LaTeX content reaches the compiler. 6. **Add regression tests.** Test filenames containing braces, backslashes, percent signs, newlines, Unicode control characters, and path-like content. The generator should reject them or produce LaTeX in which they cannot alter document syntax.
