To help prevent directory traversal attacks

Overview

safe_join

Use SafeJoin::safe_join in place of Path::join to help prevent directory traversal attacks.

A call of the form dir.safe_join(path) returns an error if any prefix of path refers to a directory outside of dir.

Example:

assert!(home_dir.join("Documents").safe_join("../.bash_logout").is_err());

Detailed explanation

safe_join tries to provide the following guarantee:

dir.safe_join(path).is_ok()

if-and-only-if, for every prefix prefix of path,

normalize(paternalize_n_x(dir.join(prefix))).starts_with(normalize(paternalize_n_x(dir)))

where the paternalize_n_x and normalize functions are as follows.

Let n be the total number of components in both dir and path. (Why this choice of n? Because this is an upper bound on the number of parent directories that dir.join(path) could possibly escape.)

Let x be any normal component that does not appear in either dir or path.

A call of the form paternalize_n_x(path):

  • prepends n copies of x to path, if path is relative
  • returns path as-is, if path is absolute

For example, suppose dir is ./w and path is y/../../z. Then n is 6. Furthermore, x is a normal component not in dir or path. So paternalize_n_x(dir) and paternalize_n_x(dir.join(path)) could be as follows:

  • paternalize_n_x(dir) = x/x/x/x/x/x/./w
  • paternalize_n_x(dir.join(path)) = x/x/x/x/x/x/./w/y/../../z

There are several path normalization functions implemented in Rust. The ones that we know about are listed below. To the best of our knowledge, the above guarantee holds using any one of them as the normalize function.

* path_clean::PathClean::clean uses strings internally, so it only works with UTF-8 paths.

Limitations

safe_join does not consult the filesystem. So, for example, in a call of the form dir.safe_join(path), safe_join would not consider:

  • whether dir is a directory
  • whether path refers to a symlink

There are a host of problems that come with consulting the filesystem. For example, a programmer might construct a path for a filesystem that is not yet mounted. We want safe_join to be applicable in such situations. So we have chosen to adopt a simple semantics that considers only a path's components.

A similar crate that does consult the filesystem is canonical_path.

Camino

safe_join optionally supports camino::Utf8Path. To take advantage of this feature, enable it on your Cargo.toml file's safe_join dependency:

safe_join = { version = "0.1", features = ["camino"] }

Linting

The safe_join repository includes a Dylint library to check for:

  • calls to Path::join where SafeJoin::safe_join could be used
  • calls to SafeJoin::safe_join that are likely erroneous because they return an error under normal circumstances (e.g., safe_join(".."))

To use the library:

  • Install cargo-dylint and dylint-link as described in the Dylint README:
    cargo install cargo-dylint dylint-link
  • Add the following to your workspace's Cargo.toml file:
    [workspace.metadata.dylint]
    libraries = [
        { git = "https://github.com/trailofbits/safe_join", pattern = "lint" },
    ]
  • Run cargo-dylint from your workspace's root directory:
    cargo dylint safe_join_lint --workspace

References

License: MIT OR Apache-2.0

You might also like...
Active Directory data collector for BloodHound written in Rust. 🦀
Active Directory data collector for BloodHound written in Rust. 🦀

RustHound Summary Limitation Description How to compile it? Using Makefile Using Dockerfile Using Cargo Linux x86_64 static version Windows static ver

Bookmark directories for easy directory-hopping in the terminal
Bookmark directories for easy directory-hopping in the terminal

markd Bookmark directories for easy directory-hopping in the terminal. All it takes is one command markd to bookmark your current directory, or use th

Convert your .NET dependencies to the Directory.Packages.props format

directory-packages-props-converter Converts your projects to use Central Package Management. PackageReference dependencies have their Version remove

⚡️(cd with env) Is a configurable cd wrapper that lets you define your environment per directory.
⚡️(cd with env) Is a configurable cd wrapper that lets you define your environment per directory.

⚡️cdwe (cd with env) A simple configurable cd wrapper that provides powerful utilities for customizing your envionment per directory. (For ZSH / BASH

Dead simple, memoized cargo subcommand to hoist cargo-built binaries into the current working directory, written in Rust.
Dead simple, memoized cargo subcommand to hoist cargo-built binaries into the current working directory, written in Rust.

cargo-hoist Dead simple cargo subcommand to hoist cargo-built binaries into scope. stable Install | User Docs | Crate Docs | Reference | Contributing

Tool to check Nixpkgs' pkgs/by-name directory

Nixpkgs pkgs/by-name checker This repository implements a program to check Nixpkgs' pkgs/by-name directory as part of RFC 140. See CONTRIBUTING.md for

Unwrap Macros to help Clean up code and improve production.

unwrap_helpers Unwrap Macros to help Clean up code and improve production. This does include a pub use of https://github.com/Mrp1Dev/loop_unwrap to ga

A CLI tool which can help you automatically kill process of your choice. Useful for freeing up memory and CPU usage!
A CLI tool which can help you automatically kill process of your choice. Useful for freeing up memory and CPU usage!

Quickiller There are always programs such as chrome that keep eating up your resources even when closed! The only way to prevent this is to kill all o

A simple cli tool to help with wordle in hard mode

Wordking A simple cli tool to help with wordle in hard mode. Usage Run wordking cargo run Wordking will ask for your guesses thus far. Provide your gu

Owner
Trail of Bits
More code: binary lifters @lifting-bits, blockchain @crytic
Trail of Bits
Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded.

Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded. It also offers image optimization and storage options. It has configurable privacy and storage settings, as well as custom cache expiration.

Thomas 4 Dec 29, 2022
lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

lemmy-help is a emmylua parser as well as a CLI which takes that parsed tree and converts it into vim help docs.

Vikas Raj 117 Jan 3, 2023
Traversal of tree-sitter Trees and any arbitrary tree with a TreeCursor-like interface

tree-sitter-traversal Traversal of tree-sitter Trees and any arbitrary tree with a TreeCursor-like interface. Using cursors, iteration over the tree c

Sebastian Mendez 12 Jan 8, 2023
dua (-> Disk Usage Analyzer) is a tool to conveniently learn about the usage of disk space of a given directory

dua (-> Disk Usage Analyzer) is a tool to conveniently learn about the usage of disk space of a given directory. It's parallel by default and will max

Sebastian Thiel 1.8k Jan 2, 2023
Jumpy is a tool that allows to quickly jump to one of the directory you've visited in the past

Jumpy Jumpy is a tool that allows to quickly jump to one of the directory you've visited in the past. It is heavily inspired by Zoxide but is more lig

Clément Nerma 2 Oct 3, 2022
A simple command line program to upload file or directory to web3.storage with optional encryption and compression

w3s-cli A simple command line program to upload file or directory to web3.storage with optional encryption and compression. Features Uploads single fi

qdwang 5 Oct 22, 2022
Minimal recursive "truncate file/directory names to meet requirements" tool

trunc_filenames ssokolow@monolith ~ % trunc_filenames --help trunc_filenames 0.1.0 Rename files and directories to fit length limits. WARNING: Will n

Stephan Sokolow 2 Nov 20, 2022
Periodically download a youtube playlist, extract audio, convert to mp3, move to directory (possibly synced using syncthing).

auto-dl Periodically download a youtube playlist, extract audio, convert to mp3, move to directory (possibly synced using syncthing). drop https://git

Paul Adenot 10 Jan 12, 2023
A simple tool to clean all projects in a directory.

Cargo Cleanall A simple tool to clean all cargo projects in a directory. Help Cargo plugin to clean all cargo projects in a directory Usage: cargo cl

null 11 Jan 24, 2023
Rsre it's tool to rename file/directory

, Rust renamer Rsre it's tool to rename file/directory Zero dependencies ?? Requirements Rust Nightly Install With Cargo # Install nightly rust rustup

Awiteb 6 Dec 22, 2022