Secure File Operations in Go with os.Root: Preventing Path Traversal

by | Nov 12, 2025

Go’s os.Root feature, introduced in Go 1.24, is designed to improve filesystem security by restricting operations to a specific directory, making it much harder for attackers to exploit path traversal vulnerabilities. This is especially valuable for scenarios like handling user-provided filenames, extracting archives, or managing static content, where you want to guarantee operations don’t accidentally impact files outside your intended root:

  • The main goal is to ensure all file operations remain confined within a defined “root” directory.​​
  • This restricts how relative paths and symlinks are handled, preventing malicious or accidental access to files outside the root (such as with ../ path traversal attempts).​
  • It is especially useful when working with untrusted file names or content, as traditional methods like filepath.Join() could be tricked into accessing unexpected locations.​
  • The os.Root type provides methods for safe file and directory operations: creating, opening, deleting, and more, all relative to the root directory and without escaping it.​

Below is a minimal example demonstrating how to use os.Root to safely create a directory and save a file inside it, while also showing how it prevents accessing files outside the root:

// Requires Go 1.24+
package main

import (
	"errors"
	"fmt"
	"os"
)

const DirPerm = os.FileMode(0755)
const FilePerm = os.FileMode(0644)

func main() {
	if err := example(); err != nil {
		_, _ = fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func example() error {
	err := os.Mkdir("/etc/go-os-root", DirPerm)
	if err != nil {
		return fmt.Errorf("failed to create root directory: %w", err)
	}

	root, err := os.OpenRoot("/etc/go-os-root")
	if err != nil {
		return fmt.Errorf("failed to open root directory: %w", err)
	}
	defer func() {
		_ = root.Close()
	}()

	// Create a subdirectory inside the root
	if err := root.Mkdir("data", DirPerm); err != nil {
		return fmt.Errorf("failed to create subdirectory: %w", err)
	}

	// Write to a file inside the subdirectory
	if err := root.WriteFile("data/example.txt", []byte("Hello, Go os.Root!"), FilePerm); err != nil {
		return fmt.Errorf("failed to write file: %w", err)
	}
	fmt.Println("File successfully written: '/etc/go-os-root/data/example.txt'")

	// Attempt to open a file outside the root via path traversal - should error
	_, err = root.Open("../passwd")
	if err == nil {
		return errors.New("unexpectedly succeeded in opening a file outside root")
	}
	fmt.Println("Prevented path traversal attempt:", err)

	return nil
}

This example safely confines filesystem operations to /etc/go-os-root directory and prevents opening files outside that root, such as ../passwd, demonstrating the core security benefit of os.Root.

You May Also Like…

 

Using Icinga 2 on NixOS

Using Icinga 2 on NixOS

I use NixOS by the way. And today I'm going to show you how to operate a simple Icinga setup using that operating...

Subscribe to our Newsletter

A monthly digest of the latest Icinga news, releases, articles and community topics.