Weakness reference
CWE-427

Uncontrolled Search Path Element

This weakness occurs when an application searches for files, libraries, or other resources using a path that includes directories controlled by an untrusted…

01Summary

This weakness occurs when an application searches for files, libraries, or other resources using a path that includes directories controlled by an untrusted user or environment. An attacker can place a malicious file in one of those search directories, causing the application to load it instead of the legitimate resource. This is particularly dangerous for executable code, configuration files, and libraries.

02How It Happens

Applications often search multiple directories in a specific order to locate resources — for example, the current working directory, system paths, or user-writable locations. If an attacker can write to any directory earlier in that search path than the legitimate resource, they can create a file with the same name. When the application searches for the resource, it finds the attacker's version first and loads it. This is especially critical when the search path includes the current working directory, temporary directories, or other world-writable locations before system or application-controlled directories.

The root cause is usually a combination of two factors: (1) the search path includes untrusted locations, and (2) the application does not validate or restrict which version of a resource it loads. Environment variables like PATH, LD_LIBRARY_PATH, or PYTHONPATH can also be manipulated to inject malicious search directories.

03Real-World Impact

An attacker exploiting this weakness can achieve arbitrary code execution by placing a malicious library or executable in a search path ahead of the legitimate one. For example, a compromised shared library loaded by a privileged process could grant the attacker elevated privileges. Configuration files loaded from untrusted paths could alter application behavior, disable security features, or redirect traffic. In multi-user systems, this can lead to privilege escalation or lateral movement between user accounts.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import sys
import importlib

# Attacker can control current working directory
sys.path.insert(0, '.')

# Application searches for 'utils' module
utils = importlib.import_module('utils')
utils.process_data(user_input)

Why it's vulnerable:
The current directory (.) is added to the module search path before system directories. An attacker who can write to the current directory can create a malicious utils.py that will be imported instead of the legitimate one.

Fixed pattern
import sys
import importlib.util

# Use absolute, application-controlled paths only
app_lib_path = '/opt/myapp/lib'
if app_lib_path not in sys.path:
    sys.path.insert(0, app_lib_path)

# Explicitly load from a known, trusted location
spec = importlib.util.spec_from_file_location(
    'utils',
    '/opt/myapp/lib/utils.py'
)
utils = importlib.util.module_from_spec(spec)
spec.loader.exec_module(utils)
Vulnerable pattern
<?php
// Application searches in current directory first
set_include_path('.' . PATH_SEPARATOR . get_include_path());

// Attacker can place malicious 'config.php' in current directory
include 'config.php';
?>

Why it's vulnerable:
The current directory is prepended to the include path. If the application runs from a directory an attacker can write to, they can create a config.php file that will be included instead of the legitimate one.

Fixed pattern
<?php
// Use only application-controlled, absolute paths
$trusted_lib_path = '/opt/myapp/includes';
set_include_path($trusted_lib_path . PATH_SEPARATOR . get_include_path());

// Explicitly include from a known location
require_once '/opt/myapp/includes/config.php';
?>

05Prevention Checklist

Remove untrusted directories from search paths.
Never include the current working directory (.), /tmp, or user-writable locations in library or module search paths. Use absolute, application-controlled paths only.
Use explicit, absolute paths for critical resources.
Instead of relying on search order, directly specify the full path to configuration files, libraries, and executables.
Validate file ownership and permissions.
Before loading a resource, verify that it is owned by a trusted user (e.g., root or the application owner) and has restrictive permissions (e.g., not world-writable).
Avoid relying on environment variables for search paths.
If you must use PATH, LD_LIBRARY_PATH, or similar, sanitize and validate them; better yet, override them with hardcoded trusted values.
Run with minimal privileges.
Limit the impact of a compromised resource by running the application with the lowest necessary privilege level.
Use code signing or integrity checks.
For critical libraries and executables, verify cryptographic signatures or checksums before loading.

06Signs You May Already Be Affected

Check for unexpected files in directories where your application runs or searches for resources — particularly in the current working directory, /tmp, or user home directories. Review application logs for failed load attempts or unusual module/library imports. If your application runs with elevated privileges, examine whether it loads resources from world-writable locations or respects untrusted environment variables.

07Related Recent Vulnerabilities