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…

 

Releasing Icinga DB v1.5.1

Releasing Icinga DB v1.5.1

Today we are announcing the release of Icinga DB version 1.5.1. This release addresses the issue of leaking SQL...

Subscribe to our Newsletter

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