Breaking out of the Tcl sandbox: when a time zone runs code
Tcl can run untrusted code in a sandbox. At SektionEins, AI-assisted analysis turned up several ways for such code to escape and run arbitrary commands with the application's full privileges. An advisory with all the details was published today.

What is Tcl?
Tcl stands for 'Tool Command Language' and is usually pronounced 'tickle'. John Ousterhout wrote it in 1988 at the University of California, Berkeley. His idea was a small scripting language that could be embedded in other programs, instead of every tool inventing its own command language. The GUI toolkit Tk followed in 1991 and still underlies Python's tkinter today.
Unless you work in one of its niches, you may never knowingly have used Tcl. It is widely used all the same: chip design tools such as Vivado and Quartus are scripted in Tcl, administrators have been automating interactive command-line programs with Expect for more than 30 years, Cisco routers and F5 load balancers can be scripted in Tcl, and SQLite's test suite is written in it. Then there are the many in-house applications that have been running quietly for years. The current version is Tcl 9, but many installations still run 8.6.
The sandbox: safe interpreters
Tcl can run untrusted code in what it calls a safe interpreter. A safe interpreter has no exec, open or socket, so the code can neither start programs nor open arbitrary files. Applications use this for plugin and macro systems, formula and rule engines or templates: anywhere users supply their own Tcl code.
A few commands are still passed through to the sandbox, but they run in the application's trusted interpreter with full privileges. One of them is clock, the command for dates and times.
The vulnerabilities
The clock command loads locale files (for month names, for example) and time zone files on demand. From a name such as de_DE or Europe/Berlin, Tcl builds a file path and runs the file as Tcl code. A regular expression is meant to stop the name from leading out of the data directory. That check had holes in several places.
From Tcl 8.6.5 (2016) onwards, the locale was not checked at all. A single line in the sandbox was enough to make the application run any file ending in .msg:
clock format 0 -gmt 1 -locale /path/to/file
In early October 2026 the Tcl developers added a check independently, as an ordinary bug fix rather than a security fix. It let tilde paths through, and Tcl 8.6 expands ~/dir/file to a path in the home directory. This bypass was reported on 20 October, and nine days later a fix was in all development branches.
Re-checking that fix turned up a second place with the same gap, the time zone option:
clock format 0 -timezone :~/dir/file
Here Tcl appends no file extension, so any file below a home directory will do. This gap has been in the code since Tcl 8.6.16 and is still open at the time of writing. Tcl 9 is not affected.
In every case the planted file runs with the application's full privileges and can, for example, start any program through exec. There is one precondition: the attacker must first be able to place a file with their own content at a known location, for instance through an upload feature. The risk is rated high (CVSS 8.3). No Tcl release with the fixes has been published yet. Each vulnerability was reproduced with a proof of concept on builds ranging from Tcl 8.5 to the current development branches.
Applications that do not use the sandbox can be affected too. A web application that passes the language from a request (?lang=en or the Accept-Language header) straight to clock or msgcat will load files of the attacker's choosing.
Two checks, the same gap
How the time zone gap came about is instructive. Up to Tcl 8.6.15, clock checked time zone names against an allowlist that permitted only letters, hyphens, underscores and slashes. Because names such as Etc/GMT+5 could not be loaded that way, it was replaced in late 2024 by a denylist that rejects absolute paths, drive letters and '..'. Nobody thought of the tilde. October's new check for locale files copied this denylist, gap and all.
When user input becomes a file name, an allowlist is almost always the better choice. It defines what is allowed, rather than relying on someone having thought of everything that is not.
What Tcl users can do now
Anyone running untrusted code in safe interpreters should check whether that code needs clock at all. If it does not, one line removes the command from the sandbox:
interp alias $child clock {}
Otherwise, wrap clock so that locale and time zone values containing path components are rejected; the advisory has a tested example. Elsewhere in the application, check locales against an allowlist before passing them to clock or msgcat.
Bear in mind, too, that a safe interpreter only restricts which commands are available. It does not limit memory or CPU time, so genuinely untrusted code should also run in a separate, unprivileged process. And once Tcl releases with the fixes are out, update.
Not the first Tcl vulnerability
Back in 2015, a vulnerability in tcllib, Tcl's standard library, was found and published at SektionEins. The html::textarea function copied form input unfiltered into the HTML output, so every application that used it was open to cross-site scripting. It was fixed within four weeks of being reported (Advisory 01/2015).
Both then and now, the reports went to the Tcl project's public ticket tracker, as the project has no private channel for security reports. The developers responded quickly this time too. What is missing is a note in the release notes that these are security fixes. Without it, Linux distribution maintainers have little reason to prioritise the updates.
Conclusion
Tcl has been around for almost 40 years and quietly does its job in a great many systems. The unchecked locale had been in the code since 2016 without anyone noticing. If you use safe interpreters, now is a good time to check whether the code in the sandbox really needs clock.
Full details, the affected versions and workarounds are in the advisory: Advisory 01/2026: Tcl safe-interpreter escapes via clock locale and time zone names
A German version of this article was also published on LinkedIn on 3 November 2026.