Go to the os.Root of a Problem

Go is giving devs a better tool against traversal attacks.
We didn’t get the chance for a news segment in this week’s Application Security Weekly podcast, but I still wanted to highlight an article that stood out to me.
Path traversal is one of my favorite appsec flaws. It’s trivial to demonstrate, easy to understand, and its related security principles lead down many…paths.
The simplest payloads rely on classic characters like dot-dot-slash (../). From there you can steer a discussion into web-related concepts like percent encoding (%2f), overlong UTF-8 encoding (%c0%af), normalization of slashes, and programming language abstractions over a file system. Once you’re onto the file system, you can hit areas of OS behavior differences, symbolic links, sandboxing, and more normalization concepts.
Then as you refine simple payloads into attack scenarios, you have opportunities that span file reads to leak useful info, file writes to clobber and create files, and file execution to run arbitrary commands. You can even sneak in a discussion of race conditions and TOCTOU-style attacks.
And now Go has defenses for devs to deal with files with the new “Traversal-resistant file APIs” in the 1.24 release.
With this API, a developer sets a root location in which file operations must be constrained. No file paths or symlinks will be able to reach outside of that root, regardless of how clever a traversal payload it might have.
This is great news for devs writing new code that has to interact with the file system. This is the kind of API that establishes a more secure design (with a few caveats) that’s resistant to mistakes and misunderstandings.
That last part is key to me when looking at an API. It doesn’t have flags that change its behavior between a safe vs. unsafe mode, it addresses a common need, and it’s extremely simple.
It’s also good news for existing code that was potentially insecure or that relied on other packages for secure file system access. Now it’s possible to make that existing code secure and reduce the amount of dependencies you rely on. (Admittedly, changing one secure implementation to another secure implementation rarely gets a high priority, but I will always like the idea of removing code and reducing dependencies when possible.)
However, the Go blog post includes caveats that show just how pernicious this vuln class remains. It notes that the underlying OS and environment may still have inconsistencies, such as Node.js remaining vulnerable to TOCTOU attacks when using these functions. Such is the life of APIs on top of APIs.
I’ll continue to experiment with more news commentary like this one. In the meantime, catch up on more news and the latest episodes at the podcast’s home.
p.s. Speaking of OS support. The Go blog post mentions Plan 9(!?) lol. Does anyone actually use that? The design philosophy of Plan 9 is that everything is a file, so it’s totally relevant to traversal. But wow there’s an OS I haven’t heard mentioned for several decades.