cybersecurity · intermediate · ~15 min · safe pentest lab

Sanitize filename against directory traversal

Enforce strict allowlists on filenames to prevent directory traversal and command flag injection.

Challenge

Path traversal attacks use ../ or separator injections to escape sandboxed storage directories and access sensitive files like /etc/passwd or overwrite configuration files.

Your Task

Implement:

int sanitize_filename(const char *raw, char *clean, size_t clean_cap);

Validate and sanitize an untrusted relative filename.

Rules

  1. If raw == NULL, clean == NULL, or clean_cap == 0, return -1.
  2. Reject and return -1 if raw:
    • Is empty ("") or equals "."
    • Starts with '-' (prevents CLI flag injection)
    • Contains ".." anywhere
    • Contains path separators '/' or '\\'
    • Contains any non-printable ASCII (< 0x20 or > 0x7E)
  3. If strlen(raw) >= clean_cap, return -1 (does not fit).
  4. Otherwise, copy raw into clean and return 0.

Example

char out[32];
sanitize_filename("report.pdf", out, sizeof out); // returns 0, out = "report.pdf"
sanitize_filename("../../etc/passwd", out, sizeof out); // returns -1 (traversal)
sanitize_filename("-rf", out, sizeof out); // returns -1 (flag injection)

Input format

raw: untrusted filename; clean: destination buffer; clean_cap: capacity of clean buffer.

Output format

Returns 0 on valid filename, -1 on any malicious or oversized path.

Constraints

Freestanding C11. Only alphanumeric, spaces, and safe printable ASCII characters allowed.

Starter code

#include <stddef.h>

/* Validate and sanitize raw filename into clean buffer (capacity clean_cap).
   Reject path separators, '..', leading '-', and non-printable characters.
   Return 0 on success, -1 on invalid or rejected filename. */
int sanitize_filename(const char *raw, char *clean, size_t clean_cap) {
    (void)raw; (void)clean; (void)clean_cap;
    return -1;
}

Common mistakes

Checking only '/' and missing '\'; failing to reject leading '-' flags; permitting '..' sequences.

Edge cases to handle

Dotfile like ".env"; path traversal like "..\foo"; raw starting with '-'; NULL pointers.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.