Safeguard
Application Security•

CWE-48 Internal Whitespace Path Equivalence and Quoting Bugs

Spaces inside filenames cause unquoted command arguments and query string tricks. CWE-48 explained with a fix you can apply today.

Safeguard Security Team
3 min read

Spaces in the middle of a filename sound like an annoyance, not a vulnerability. CWE-48 is path equivalence using internal whitespace, file name, where the product accepts such input without appropriate validation and ends up with ambiguous path resolution.

It sits in the same family as CWE-41. What makes the internal space case distinctive in the record is that it shows up in two very different ways.

How it happens

First, unquoted names. CVE-2000-0293 is recorded as filenames with spaces allowing arbitrary file deletion when the product does not properly quote them, with some overlap with path traversal. If a program builds a command line or a path list from a name and splits on whitespace, one filename becomes two arguments. A file called report final.txt turns into report and final.txt, and an attacker who names a file x /etc/important can point an operation at a path of their choosing.

Second, URL decoding. CVE-2001-1567 is a case where + characters in a query string were converted to spaces before a sensitive file or extension was checked, which let an attacker bypass access restrictions on the file. The access rule saw one string and the later step saw another.

# Vulnerable: shell string built from a name with spaces
import os
os.system("rm /srv/tmp/" + filename)     # "a /etc/passwd" deletes two things

What an attacker gains

MITRE lists reading and modifying files and directories. The deletion example above shows integrity and availability impact, and the query string example shows access control bypass.

How to find it

Grep for code that builds shell commands or argument strings from filenames. Test endpoints with names that contain spaces and with + and %20 in the query string. Compare the access decision for each spelling against the plain name.

How to fix it

  • Never build commands by string concatenation. Pass arguments as a list or use the language's file API directly.
  • Apply access rules after URL decoding, never before.
  • Validate names against an allowlist that excludes whitespace unless it is truly required.
import os
os.remove(os.path.join("/srv/tmp", filename))      # no shell, one path

If you must call an external program, pass the name as a separate argument, for example with subprocess.run(["rm", "--", path]), so it is never re-split.

Quick check

How can a space cause a deletion bug?

An unquoted name is split into several arguments by the shell or a parser, so the command acts on a path the attacker supplied inside the name.

What is the fix for the plus sign case?

Decode the query first, then run the access check on the decoded value, so the rule sees the same string the file layer will use.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.