ASVS 5.0 V1.2.8 (Level 2) requires that any LaTeX processor your application runs is configured securely, which means no --shell-escape, and that an allowlist of commands is enforced so users cannot inject dangerous LaTeX. It matters for apps that turn user text into PDFs, such as invoices, reports and certificates.
Why it matters
LaTeX is a programming language. With shell escape on, a document can run operating system commands. Even without it, commands like \input and \include can read local files, and \write18 style features can write them. A user who controls part of the source can read /etc/passwd into the PDF.
How to implement it
Run the processor with restrictions and treat user text as data, not markup.
import subprocess, tempfile, pathlib
def render(tex_source: str) -> bytes:
with tempfile.TemporaryDirectory() as d:
src = pathlib.Path(d, "doc.tex")
src.write_text(tex_source, encoding="utf-8")
subprocess.run(
["pdflatex", "-no-shell-escape", "-interaction=nonstopmode",
"-halt-on-error", "-output-directory", d, str(src)],
cwd=d, timeout=20, check=True, capture_output=True,
env={"openin_any": "p", "openout_any": "p", "PATH": "/usr/bin"},
)
return pathlib.Path(d, "doc.pdf").read_bytes()
The environment values set openin_any and openout_any to paranoid mode, which limits file access. Better still, escape user text so it can never form a command: replace the backslash, braces, $, &, #, _, %, ^ and ~ with their safe forms before placing it into a template you control. Run the process in a container with no network and a read only filesystem apart from the working folder.
How to test it
Put \input{/etc/passwd} and \immediate\write18{id} in a user field. The PDF must contain the literal text or the build must fail. Check the command line for -no-shell-escape or -shell-restricted and confirm that your TeX configuration does not enable shell_escape = t.
Common mistakes
- Enabling shell escape for one package and never turning it off.
- Passing user supplied source files rather than filling a fixed template.
- Running the compiler as the application account with full file access.
Quick check
Is disabling shell escape enough?
No. File read commands still exist, so also escape user text, restrict file access and sandbox the process.