Inclusion of Functionality from Untrusted Control Sphere
This weakness occurs when an application loads and executes code, libraries, or scripts from a source outside its intended control — such as a user-supplied…
This weakness occurs when an application loads and executes code, libraries, or scripts from a source outside its intended control — such as a user-supplied path, an unverified remote server, or a package repository without integrity checks. An attacker who can influence which code gets loaded can inject malicious functionality directly into the application's runtime, bypassing many traditional security controls.
02How It Happens
Applications often need to load external code: plugins, libraries, configuration files, or remote resources. The vulnerability arises when the source or path of that code is not strictly controlled by the developer. Common patterns include:
- Dynamic imports based on user input: Loading a module or file whose name comes from a query parameter, form field, or configuration file without validation.
- Unverified remote includes: Fetching and executing code from a URL without verifying its authenticity or integrity (no signature check, no HTTPS pinning, no hash verification).
- Insecure package/dependency resolution: Installing dependencies from a repository without checking package signatures, or allowing a man-in-the-middle attacker to intercept and replace a legitimate package.
- Writable include paths: Including files from directories where an attacker can write (e.g., /tmp, a world-writable upload folder, or a shared hosting directory).
The core issue is that the application trusts the source of the code without verifying it belongs to the intended author or has not been tampered with.
03Real-World Impact
Successful exploitation grants an attacker arbitrary code execution within the application's privilege context. This can lead to:
- Complete application compromise: The attacker's code runs with the same permissions as the web server or application process.
- Data theft: Access to databases, configuration files, user data, and secrets stored in memory or on disk.
- Lateral movement: Using the compromised application as a pivot point to attack other systems on the network.
- Supply chain attacks: If the application is a library or service used by others, the attacker can compromise downstream users.
The severity is typically critical because code execution is the highest-impact outcome.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import importlib
import sys
# User supplies a module name via a web request
user_module = request.args.get('module')
# Dynamically import the module without validation
module = importlib.import_module(user_module)
result = module.process_data(data)
Why it's vulnerable: An attacker can supply a module name like os or a path to a malicious module they've placed on the system, causing arbitrary code to execute during import.
Fixed pattern
import importlib
# Whitelist of allowed modules
ALLOWED_MODULES = {'data_processor', 'validator', 'formatter'}
user_module = request.args.get('module')
if user_module not in ALLOWED_MODULES:
raise ValueError(f"Module '{user_module}' is not allowed")
module = importlib.import_module(user_module)
result = module.process_data(data)
Vulnerable pattern
<?php
// User supplies a plugin name
$plugin = $_GET['plugin'];
// Directly include the file without validation
include('/var/www/plugins/' . $plugin . '.php');
?>
Why it's vulnerable: An attacker can supply a path like ../../../etc/passwd or a filename pointing to a file they control, causing arbitrary code execution or information disclosure.
Fixed pattern
<?php
// Whitelist of allowed plugins
$allowed_plugins = ['user_auth', 'email_handler', 'logging'];
$plugin = $_GET['plugin'] ?? '';
if (!in_array($plugin, $allowed_plugins, true)) {
die('Invalid plugin');
}
// Safely include only from the intended directory
$plugin_path = '/var/www/plugins/' . $plugin . '.php';
if (file_exists($plugin_path) && is_file($plugin_path)) {
include($plugin_path);
} else {
die('Plugin not found');
}
?>
05Prevention Checklist
Use allowlists, not blocklists. Maintain an explicit list of approved modules, plugins, or libraries; reject anything not on it.
Verify code integrity. For remote includes, use cryptographic signatures (GPG, code signing certificates) or cryptographic hashes to confirm the code hasn't been tampered with.
Pin dependencies. Use lock files (e.g., requirements.txt with exact versions, composer.lock) and verify checksums of downloaded packages.
Avoid dynamic imports from user input. If you must load code dynamically, derive the name from a fixed mapping or configuration, never directly from user-supplied data.
Restrict file paths. Use absolute paths and realpath() checks to prevent directory traversal; never include from world-writable directories.
Use HTTPS and certificate pinning. If fetching code remotely, enforce HTTPS and validate the server's certificate to prevent man-in-the-middle attacks.
06Signs You May Already Be Affected
- Unexpected files or directories in your plugins, modules, or vendor folders that you did not install.
- Unusual entries in your application logs showing failed or successful imports of unexpected modules.
- Unexpected outbound network connections from your application to unfamiliar domains.
- Presence of suspicious code in configuration files or auto-loaded scripts that you did not write.