What does \write18 mean?

I recently talked about converting eps files to pdf format, and mentioned that to do it from within TeX, you need \write18 enabled. However, I failed to say what that means: probably not very helpful.

The TeX \write primitive instruction is used to write to different file ‘streams’; TeX refers to each open file by number, not by name (although most of the time we hide this). Stream 18 is special: it is not a file but means that TeX asking the operative system to do something. To run a command, we put it as the argument to \write18. So to run the epstopdf program on a file with name stored as \epsfilename, we’d do:

\write18{epstopf \epsfilename}

When using something like the epstopdf LaTeX package, that is hidden away and you don’t need to worry about the exact way it’s done. I’m not going to worry about the detail of the \write instruction here!

However, there is a security issue. If you download some TeX code from the Internet, can you be sure that there is not some command in it (perhaps in a hidden way) to do stuff that might be harmful to your PC (lets say delete everything on the hard disk!). So both MiKTeX and TeX Live have traditionally disabled \write18 as standard. To turn it on, both support an additional argument when starting TeX:

(pdf)(la)tex --shell-escape

The problem with this is that most people use (La)TeX via a graphical editor, and each one needs the correct settings changing to use \write18 for every file. It’s also not such a great idea to turn it on for everything: it rather defeats the point of it being off by default!

The latest version of MiKTeX (2.8), and the upcoming TeX Live release (2009) get around this by having a special ‘limited’ version of \write18 enabled ‘out of the box’. The idea is to allow only a pre-set list of commands (for example, BibTeX, epstopdf, TeX itself, and so on). Those on the list are regarded as safe enough to allow, whereas anything else (for example deleting files) still needs to be authorised by the user. This seems to be a good balance: most people most of the time will not need to worry about \write18 at all, but it will be available for things like epstopdf.

19 thoughts on “What does \write18 mean?

  1. I’d like to mention that TeX itself it is not safe at all, due to its
    –shell-escape option. A malicious document could (using normal write) create a
    file bomb.tex containing write18{rm -rf ~} (on Unix) and then do write18{tex
    –shell-escape bomb.tex}.

    That’s the reason why tex is not in the default list of authorized programs in
    TeX Live.

  2. Pingback: Jürgen Fenn (juergenfenn) 's status on Tuesday, 06-Oct-09 22:29:15 UTC - Identi.ca
  3. @Manue: It would be good if TL could include a “restricted” version of pdfTeX itself that could be called from within a restricted-shell escape invocation without itself being a security hazard. I don’t know what the technical/infrastructure challenges around this could be, however,

  4. Manue,

    Thanks for that correction. Is there a documented list of the commands allowed somewhere? I’d guess Will’s idea is actually not possible: the nearest would be to have a “safepdftex” command that can’t be used with full write18 enabled. Am I correct?


  5. Yes, my understanding is that you’d need an entirely separate binary. (This is what Heiko has done with (r)pdfcrop.)

  6. I think this is a really bad idea. We get lots of potential security issues, and the only thing we gain is not having to check some checkbox in a GUI or add a flag when using the CLI.

    Looking at http://www.tug.org/svn/texlive/trunk/Master/texmf/web2c/texmf.cnf?view=markup it seems as if the “safe” commands are: bibtex, bibtex8, epstopdf, epspdf, fc-match, kpsewhich, makeindex, ps2pdf, pstopdf, rpdfcrop.

    On my system “ps2pdf valid.ps any-file” will happily overwrite “any-file”, negating openout_any-restrictions, epspdf has a –psoptions flag whose argument appears to be added to the system() call unquoted (just had a quick look, might be wrong on that one), …

    Instead there should be a flag –allowed-shell-commands=…, with the GUIs providing defaults that they consider sensible (perhaps based on the packages used).

  7. I’m not a developer for either MiKTeX or TeX Live, so I can only say what I imagine is the thinking.

    For a single arbitrary file, you can overwrite with no warning without write18 at all, just using TeX. After all, this is what LaTeX does with the .aux file (plus others). So there is no real difference in letting other tools that can write to a single file run. The worry is mainly real shell escape, such as “cd .. && rm -rf *” (on Unix, of course).

    I’ve said before that the real risk of write18 is pretty low (people wanting to do evil things usually find rather more general ways than via TeX)! So I personally feel the trade off here is worth it.

    On thing you have to remember is most users rely on a GUI, and find it *very* confusing getting instructions like “Change the parameters sent to LaTeX to include -shell-escape”. Arguing that the GUI should add stuff automatically assumes that every GUI is updated to fit the scheme. What list you you go for in any case? One of the key reasons for this change is because using EPS graphics with PDF output is a *real* problem for many users.


  8. Concerning overwriting files: I did say “negating openout_any-restrictions”. Today, by default, you can only overwrite files “below” the current document, or at absolute paths in $TEXMFOUTPUT. With the new version, someone will be able to overwrite every single file you have.

    Concerning this being “low risk”: I agree that we probably won’t see any worms using this method, TeX is way too small for that. However, it might very well be used to launch an attack against a specific person (researcher). Knowing that only I, or a handful others, were attacked does not comfort me.

    Concerning GUIs: it shouldn’t be very hard even now, just Google “name-of-your-gui shell-escape”.

    To make it “automatic”, packages that require external binaries should include directives stating whatever they need, in some (yet to be specified) standard fashion. It could be a directive in the source, or a specially formatted error message (“pragma-need-binary: epstopdf OR eps2pdf”). The GUI would then ask the user if they want to allow binary X for this document, and if so recompile with –allowed-shell-commands=X (a new flag).

    You seem to think that security issues are not real problems. I beg to differ. Didn’t macros in Microsoft Word teach us anything? Of course we can have both EPS-conversion and security. That’s why it is so very unfortunate that the present change makes TeX worse than the latest verison of Microsoft Word, from a security point of view.

    If you look at the commits, you’ll see that the developers actually tried to only include “safe” binaries. Unfortunately, they failed miserably. If we are to allow any automatic execution of external binaries, it should only be for a small subset of binaries that are included in the distribution of TeX. Each program should do only one simple thing, to make it easy to audit.

  9. @”user”: please report problems with restricted shell escape on the TeX Live mailing list. Effort has been made to try and keep things both secure and convenient but here isn’t the place to report that the implementers have failed at doing this.

  10. user,

    A message to the TeX Live list today states that the feature has been disabled (at least for the moment) for the reason you outline (bypassing openout_any-restrictions). So the it looks to me like the TeX Live team do take this kind of concern seriously.


  11. Pingback: Automatically run makeindex from within a LaTeX-document with write18 » Beitrag » Freiheitsfreund
  12. Pingback: รัน shell command จาก Latex | Wittawat's Blog
  13. This command is usually needed when the file.tex contains a filecontents* environment with some image file transformed with base64. In this way it is possible to have in one tex file everything needed to produce a document.

    In this context, immediatewrite18{} is used to decode the needed files generated by the filecontents* environment.

    An alternative is to also use the filecontents* environment to produce either a shell scripts or a Makefile, with the commands to decode the needed files and to erase the temporal files generated by this process.

    It can be used for example, to build a beamer template that includes the logo the institution in a way that only one file is needed to distribute among all the users of beamer in that institution.

    The work flow is something like this:

    1) encode the logo.png file with base64
    2) put the contents of the encoded file in a begin{filecontents*}{logo.png.base64} environment
    3) either use write18 or generate scripts (both sh,bat) or a Makefile to decode the generated file with the appropriate commands like:
    base64 -d logo.png.base64 > logo.png
    4) distribute a pdf file with the instructions for the customized beamer template explaining how to compile it with –sell-escape or by executing the generated shell script.

    Or you simply want to use this features for a better organization of your files as an alternative to use a tar,rar or zip file.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.