Since "ns_mktemp" is deprecated (on the C level) and is prone to vulnerabilities. This effects as well "ad_tmpnam" in OpenACS, which uses "ns_mktemp".
Newer C-compilers complain about this more loudly:
Due to security concerns inherent in the design of mktemp(3), it is highly recommended that you use mkstemp(3) instead.
The security concern is that when ns_mktemp() is used to generate a (unique) file name, which is used for opening a file, an attacker can intercept the running binary and sneak in a different file. Although ns_mktemp() guarantees to return a unique file name, there is no mechanism to prevent another process or an attacker from creating a file with the same name before the application attempts to open it.
The problem with using mkstemp() instead is that it has different semantics, since it returns the open file. So one cannot blindly replace these calls, but it requires some refactoring. Unfortunately, this also effects application code, since NaviServer offers "ns_mktemp" on the Tcl level.
To make it short: one has to separate out different use_cases of "ad_tmpnam": (a) use it to obtain a name for creating a file, which is subsequently opened (b) use it to obtain a name for creating a directory (c) use it as a name, providing name as a unique name to some external programs.
Case (a) is similar to the "mkstemp(3)" recommendation above. For this usage scenario, the call "file tmpfile..." in Tcl 8.6 can be used (but it should also respect the configured tmp directory. This function is also very similar to "ns_opentempdir" in NaviServer, which uses as well "file tmpfile". Therefore, we have created a new API call "ad_opentmpdir ..." which respects the OpenACS settings.
Case (b) can be addressed by "file tempdir" in Tcl 8.7, or by a function in tcllib. The new API function "ad_mktmpdir" provides respects the OpenACS settings, and works for Tcl 8.6 or newer.
Case (c) is somewhat different, since it just wants to create a unique name. This case has not received a special API so far
which calls Tcl's "uplevel" with two arguments. In this case, the arguments are concatenated and the evaluated in the caller's frame. There is a substitution before the evaluation. When just one argument is passed in, this problem there is only one evaluation: