CWE-426 applies when a product searches for critical resources using an externally supplied search path that can point to resources the product does not control. MITRE says this can let attackers execute their own programs, access unauthorized data files or modify configuration.
It hits installers, setuid programs, services, scripts and anything that shells out to another tool by bare name.
How it happens
The classic form is the PATH environment variable. If a program runs backup without a full path, the system walks the directories in PATH and runs the first match. If an attacker controls PATH, or can put a file early in it, their program runs instead.
MITRE gives the common variants. On Unix and Linux, PATH may be used to locate executables, and LD_PRELOAD can name a library to load. On Windows, PATH is consulted to locate a DLL if the DLL is not found in earlier locations.
import subprocess
# Vulnerable: resolves "tar" through the caller's PATH
subprocess.run(["tar", "czf", "out.tgz", "data/"])
Observed examples from MITRE:
- An application relying on its PATH environment variable to find and execute a program (CVE-1999-1120).
- A database application doing the same (CVE-2008-1810).
- A chain where an untrusted search path let malicious internationalization messages load, resulting in a format string bug (CVE-2007-2027).
- A malicious .EXE found through an untrusted search path on Windows (CVE-2008-3485).
What an attacker gains
Per the record: arbitrary code execution with the privileges of the vulnerable program, which affects integrity, confidentiality, availability and access control. Other outcomes include a crash or hang when the program is redirected to a file that is too large or malformed, and disclosure of files through output sent to the attacker.
How to find it
MITRE lists three approaches:
- Black box monitoring. Watch the process as it interacts with the operating system and network. This works when you have no source, or when you want to confirm that a build did not introduce the problem.
- Automated static analysis. Can find some instances by modeling data flow.
- Manual analysis. Penetration testing and threat modeling, which can be more effective for this weakness.
A quick manual check is to grep for process execution calls and look at whether they use bare names:
grep -rnE "system\(|popen\(|exec[lv]p?\(|subprocess" src/
How to fix it
- Use absolute paths for programs and libraries you launch.
- Do not trust the environment. For privileged programs, set PATH explicitly or clear it, and ignore user supplied library paths.
- Avoid shelling out when a library call does the same job.
- Lock down directories. Directories that appear in a search path should not be writable by untrusted users.
- Monitor at runtime for unexpected child processes and library loads.
import subprocess
# Fixed: absolute path, no shell
subprocess.run(["/usr/bin/tar", "czf", "out.tgz", "data/"], check=True)
Quick check
Why is a bare command name risky?
The system picks the first matching file from a list of directories. If an attacker can influence that list or one of those directories, they choose what runs.
Is clearing PATH enough for a privileged program?
It helps, but also use absolute paths and ignore other user controlled variables such as library preload settings.