💾 Archived View for dj-chase.com › documents › mktemp-isnt-posix.html captured on 2024-08-18 at 18:15:36.

View Raw

More Information

⬅️ Previous capture (2024-03-21)

-=-=-=-=-=-=-

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>
      PSA: mktemp Isn’t POSIX
    </title>
    <meta name="generator" content="//dj-chase.com/Make.py">
    <link rel="stylesheet" href="../style.css?cache-bust=2024-02-15">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
    <nav>
      <a href="#start">Skip to start</a>
      <!-- screen-reader–only p -->
      <p>You are here:</p>
      <ol>
        <li><a href="/" aria-label="home">⌂&nbsp;<span>›</span></a></li>
        <li><a href="/documents/">documents&nbsp;<span>›</span></a></li>
        <li><a href="/documents/mktemp-isnt-posix.gmi">mktemp-isnt-posix.gmi</a></li>
      </ol>
    </nav>
    <main id="start">
      <h1>
        PSA: mktemp Isn’t POSIX
      </h1>
      <p>
        I’ve noticed quite a few shell scripts recently that claim to be POSIX-compliant despite using mktemp, so I wanted to go over a compliant alternative and a few things you should know about writing POSIX shell (<code>#!/bin/sh</code>) scripts.
      </p>
      <h2>
        Problems
      </h2>
      <p>
        Temporary files aren’t easy. They seem easy, but there are a lot of small details that cause security vulnerabilities if done incorrectly.[1] The best solution to this problem is to use mktemp(1), but that’s not guaranteed to be on all systems. Even if you’re comfortable assuming that mktemp will be present, its syntax differs on different systems.[2][3]
      </p>
      <h2>
        Solutions
      </h2>
      <p>
        As mentioned in [1], you could just avoid using temporary files — a multiline variable is often sufficient. If you absolutely need a temporary file, consider using the following function instead of relying on mktemp:
      </p>
      <pre>
# POSIX sh lacks mktemp
mktemp() {
        # usage: file="$(mktemp [-d])"
        mktempOldUmask="$(umask)"
        umask u=rw,g=,o=

        if [ "$1" = "-d" ]; then
                # don't use m4 because it lacks mkdtemp()

                # use awk for randomness because POSIX sh lacks $RANDOM,
                # /dev/[u]rand, shuf, …
                printf '%s%s\n' "${TMPDIR:-/tmp}/tmp.$." \
                        "$(awk 'BEGIN{srand();printf("%d\n", rand()*10^7);}')" \
                | xargs -I _ -- sh -c "mkdir -m u=rwx,g=,o= _ &amp;& echo _"
        else
                # use m4 to use the real mkstemp() function
                printf '%s\n' "mkstemp(${TMPDIR:-/tmp}/tmp.XXXXXXX)" | m4
        fi

        umask "$mktempOldUmask"
}
</pre>
      <p>
        This uses m4’s <code>mkstemp()</code> function (which <em>is</em> specified POSIX) for the creation of regular temporary files, and a racefree shell-solution for temporary directories.
      </p>
      <h2>
        Things to know
      </h2>
      <ul>
        <li>When writing a POSIX shellscript, make sure the commands you’re using are actually available in POSIX shell. You can do this easily by looking in the <code>1p</code> and <code>8p</code> sections of the manual.
        </li>
        <li>Even if you know a command is specified by POSIX, still consider looking at the manual; Often commands will have slightly different syntax or fewer options than you’re used to.
        </li>
        <li>Use <a href="https://www.shellcheck.net/">shellcheck</a>.
        </li>
      </ul>
      <h2>
        Sources
      </h2>
      <ol>
        <li>Jan Schaumann, “Safely Creating And Using Temporary Files” In “Signs of Triviality”. 2017-06-05. <a href="https://www.netmeister.org/blog/mktemp.html">https://www.netmeister.org/blog/mktemp.html</a>
        </li>
        <li>Bruce Korb, “mktemp - Make a Temporary File or Directory”. 2002, updated 2014-08-30. <a href="https://www.gnu.org/software/autogen/mktemp.html">https://www.gnu.org/software/autogen/mktemp.html</a>
        </li>
        <li>Todd Miller, “Mktemp Manual”. 2014, updated 2015-11-22. <a href="https://www.mktemp.org/manual.html">https://www.mktemp.org/manual.html</a>
        </li>
      </ol><!-- html code generated by txt2tags 3.3 (http://txt2tags.org) -->
      <footer>
        <p>
          Questions, comments, or wrote a reply? <a href="mailto:u9000@posteo.mx">Email me</a>.
        </p>
        <p>
          ©&nbsp;DJ Chase 2022-09-18. Licensed under the Academic Free License (AFL&nbsp;3.0).
        </p>
        <p>
          <a href="/cgi-bin/cite.sh">Cite this page</a>
        </p>
        <p>
          <a href="https://u9.tel/mktemp-isnt-posix">Short link</a>
        </p>
      </footer><!-- cmdline: txt2tags  -->
    </main>
  </body>
</html>