# How can I safely compile other people's LaTeX documents?

I am a programmer and as part of a website I need to be able to take LaTeX source files and compile them, then return the pdf to the user. This seems dangerous since a malicious user could e.g. read and write files on server this way. Is it possible to 'clean' a LaTeX file so it's safe to compile or is it too complicated?

-
There was an article about this in a recent issue of TUGBoat... –  Seamus Feb 6 '11 at 19:33
Here's a link to the issue number It's called "A web-based TeX previewer". It is currently only available to TUG members, but it should be available to non member soon... (I think?) –  Seamus Feb 6 '11 at 19:36
The site says it will be available in September, one year after it was published. –  swampsjohn Feb 6 '11 at 19:54
Oh right. Well I'll come back and summarise the points it makes when I have a minute... –  Seamus Feb 7 '11 at 10:59

In texmf.cnf there are some options to restrict what TeX documents can do. The most important, from a security viewpoint (with the values in my local texmf.cnf, which may or may not be the default on your system):

% Enable system commands via \write18{...}.  When enabled fully (set to
% 1), obviously insecure.  When enabled partially (set to p), only the
% commands listed in shell_escape_commands are allowed.  Although this
% is not fully secure either, it is much better, and so useful that we
% enable it for everything but bare tex.
shell_escape = p

% Special: convert is the standard command name for ImageMagick, but it
% is also the name of a dangerous filesystem-changing command on
% Windows.  So enable imgconvert (used in w32tex), but not convert.

% No spaces in this command list.
shell_escape_commands = \
bibtex,bibtex8,dvips,epstopdf,epspdf,etex,fc-match,\
imgconvert,\
kpsewhich,makeindex,mkgrkindex,\
pdfluatex,ps2pdf,ps4pdf,pstopdf,pygmentize,\
rpdfcrop,texindy,xindy,ulqda\

% plain TeX should remain unenhanced.
shell_escape.tex = f


I think you may want to set this simply to shell_escape = f.

% Allow TeX \openin, \openout, or \input on filenames starting with .'
% (e.g., .rhosts) or outside the current tree (e.g., /etc/passwd)?
% a (any)        : any file can be opened.
% r (restricted) : disallow opening "dotfiles".
% p (paranoid)   : as 'r' and disallow going to parent directories, and
%                  restrict absolute paths to be under \$TEXMFOUTPUT.
openout_any = p
openin_any = a


This allows anyone to read any files on your system (if the user has the necessary rights), so maybe you'll want to change this, too.

% Allow TeX and MF to parse the first line of an input file for
% the %&format construct.
parse_first_line = t


This may lead to the tex files being read with another macro package than intended - I don't know whether this is critical, but you should think about it.

% Enable the mktex... scripts by default?  These must be set to 0 or 1.
% Particular programs can and do override these settings, for example
% dvips's -M option.  Your first chance to specify whether the scripts
% are invoked by default is at configure time.
%
% These values are ignored if the script names are changed; e.g., if you
% set DVIPSMAKEPK to foo', what counts is the value of the environment
% variable/config value FOO', not the MKTEXPK' value.
%
% MKTEXTEX = 0
% MKTEXPK = 0
% MKTEXMF = 0
% MKTEXTFM = 0
% MKTEXFMT = 0
% MKOCP = 0
% MKOFM = 0


These settings (or non-settings) decide whether needed files (like fonts/font metrics) are automatically generated when needed. I don't know whether this would be a security risk, but it certainly can prolong compilation.

Later there are some memory limits to set, which also may be useful.

You can change these settings globally in your texmf.cnf, or give them as environment variables to the programs invoked (environment takes precedence).

Some options may also be given on the command line.

-
+1, especially the openout_any=p and openin_any=p options look VERY promising. No real need for chroot anymore. –  Martin Scharrer Feb 7 '11 at 7:51
Be aware that a malicious loop could spike the CPU indefinitely. –  Dave Jarvis Mar 14 '13 at 17:00

in the configuration texmf.cnf file you can disallow the execution of external programs. Run kpsewhich texmf.cnf to find the location of your file.

-

You could filter for some specific macros, but there is most definitely a way to overcome this. TeX is a very complicated language to parse if you don't use TeX itself for it.

You need to make sure that the -shell-escape option is disabled, which is already the default. The global setting is in texmf.cnf but can be overwritten by -no-shell-escape anyway.

You might want to use the -output-directory option or run the latex compiler in a safe directory. However this doesn't prevent the document to read and write files in another directories.

For a Unix-like OS I would recommend to run it in a chroot environment with minimal system files present under a user which has only minimal read and write permissions. This plus disabled shell-escape should make it very safe.

-
Yeah, I figured I'd probably need to use chroot. I'm just worried because I only need to miss one way to do something malicious for something bad to happen. For example since TeX is Turing-complete couldn't someone write a tex file that never finishes compiling? I'm sure I could lock down most attack vectors but I'll never be sure that it's safe 100% =/ –  swampsjohn Feb 6 '11 at 19:59
Sure you can program a endless loop: \def\endless{\endless}\endless, you would need to set some time, process and size limits. –  Martin Scharrer Feb 6 '11 at 20:08
Actually, with current TeXlive the default for shell-escape is to allow certain commands. You may want to switch this of totally. (Set shell_escape = f in texmf.cnf.) –  Paŭlo Ebermann Feb 7 '11 at 0:00
The TUGBoat article mentions those kind of endless loops. It also mentions similar dangers like an an endless loop that creates a \newpage at every step, thus eating memory as well... –  Seamus Feb 7 '11 at 10:59