IT Security 1 month ago

Configuration Injection Vulnerability in virtualenv – What You Need to Know

A critical configuration injection vulnerability in virtualenv allows attackers to inject malicious settings into the pyvenv.cfg file via the prompt parameter, potentially leading to arbitrary code execution. This guide explains the flaw, affected versions, detection techniques, and immediate A critical configuration injection vulnerability in virtualenv allows attackers to inject malicious settings into the pyvenv.cfg file via the prompt parameter, potentially leading to arbitrary code execution. This…

IT Security

Executive Summary

A configuration injection vulnerability exists in virtualenv, a widely-used tool for creating isolated Python environments. The vulnerability stems from improper handling of line boundaries in the pyvenv.cfg configuration file, allowing attackers to inject malicious settings through user-supplied input. By crafting specially-formatted prompt values, an attacker can redirect the base interpreter path to a malicious location, potentially leading to arbitrary code execution or unauthorized data access.

This advisory provides technical details, affected systems, detection methods, and actionable mitigation strategies for organizations using virtualenv in their Python development and deployment workflows.


Understanding the Vulnerability

How Configuration Injection Works

The pyvenv.cfg file uses a line-based format to store critical configuration parameters for Python virtual environments. The vulnerability arises from the way virtualenv handles the prompt value—a user-configurable setting that can be specified through multiple input vectors:

  • The --prompt command-line option
  • The VIRTUALENV_PROMPT environment variable
  • Configuration files passed during environment creation

The PyEnvCfg.write() method writes prompt values directly to the configuration file without sanitizing line boundary characters (newlines). When PyEnvCfg._read_values() parses the file using str.splitlines(), it interprets these injected line breaks as separate configuration entries, allowing attackers to add unauthorized key-value pairs.

Example of exploitation:

# Legitimate prompt value
--prompt="my-env"
# Malicious prompt value containing line injection
--prompt="my-env
home=/path/to/malicious/interpreter"

When written to pyvenv.cfg, this creates:

prompt = my-env
home = /path/to/malicious/interpreter

Why virtualenv Is Affected

The root cause lies in two design decisions:

  1. No escape syntax: The pyvenv.cfg format lacks an escape mechanism for special characters, making it impossible to safely include line breaks in values.
  2. Direct input handling: User-supplied data is written to the configuration file without validation or sanitization of line boundary characters.

This combination creates a direct path from user input to configuration file manipulation, bypassing the intended configuration hierarchy.

The pyvenv.cfg File and Its Role

The pyvenv.cfg file is the configuration backbone of Python virtual environments. It stores critical settings including:

  • home: The path to the base Python interpreter
  • prompt: The virtual environment name displayed in shell prompts
  • include-system-site-packages: Whether to include system packages
  • version: The Python version used to create the environment

The home parameter is particularly sensitive, as it determines which Python interpreter executes code within the virtual environment. Redirecting this path to a malicious location effectively compromises the entire environment.


Which Systems Are at Risk

Affected Versions

All versions of virtualenv that utilize the PyEnvCfg.write() and PyEnvCfg._read_values() methods without proper line boundary sanitization are vulnerable. This includes:

  • virtualenv 20.x and earlier
  • Any custom or forked versions using the same vulnerable code patterns

Check your installed version:

pip show virtualenv

Vulnerable Components

The vulnerability affects:

  • Direct virtualenv usage: Applications or scripts that create virtual environments programmatically
  • Wrapper tools: Any tool that invokes virtualenv with user-supplied prompt values
  • Automation frameworks: CI/CD systems, deployment tools, and orchestration platforms
  • Development workflows: Teams using virtualenv in shared or multi-tenant environments

Common Deployment Scenarios

High-risk scenarios include:

  1. CI/CD Pipelines: Build systems that set VIRTUALENV_PROMPT using branch names, commit hashes, or user identifiers
  2. Shared Development Servers: Multi-user systems where environment variables can be set by different users
  3. Container Orchestration: Kubernetes or Docker environments where environment variables are dynamically injected
  4. Automated Provisioning: Infrastructure-as-Code tools that create virtual environments with user-supplied parameters
  5. Web Applications: Applications that generate virtual environments based on user input

Real-World Attack Scenarios

CI/CD Pipeline Exploitation

Scenario: A development team uses GitLab CI to test Python packages. The CI configuration sets the virtual environment prompt to the branch name:

before_script:
  - export VIRTUALENV_PROMPT=$CI_COMMIT_REF_NAME
  - python -m virtualenv venv

An attacker creates a malicious branch with a name containing line injection:

feature/test
home=/tmp/malicious-python

When the CI pipeline runs, it creates a virtual environment with a redirected interpreter path. Subsequent test runs execute code from the attacker’s malicious Python installation.

Impact: Arbitrary code execution in the CI/CD environment, potential access to secrets, credentials, and source code.

Environment Variable Injection

Scenario: A shared development server allows users to set environment variables. An attacker with local access sets:

export VIRTUALENV_PROMPT="dev-env
home=/home/attacker/python-trap"

When other developers create virtual environments on this server, their environments are silently redirected to the attacker’s Python installation, which could be modified to log credentials or inject malicious packages.

Impact: Lateral movement, credential theft, supply chain compromise.

User Input Manipulation Attacks

Scenario: A web application allows users to create isolated Python environments for running user-submitted code. The application uses the username as the prompt:

prompt_value = request.form['username']
os.system(f'python -m virtualenv --prompt={prompt_value} user_env')

An attacker submits a username containing:

attacker
home=/var/www/malicious

The resulting virtual environment executes code using the attacker’s Python installation, potentially compromising the entire application.

Impact: Remote code execution, data exfiltration, application compromise.


Security Impact and Risk Assessment

Potential Consequences of Exploitation

Successful exploitation of this vulnerability can lead to:

  • Arbitrary Code Execution: Malicious Python code executes with the privileges of the user running the virtual environment
  • Supply Chain Compromise: Injected code could modify packages, inject backdoors, or steal credentials
  • Data Exfiltration: Access to sensitive data processed by Python applications
  • Privilege Escalation: In some scenarios, exploitation could lead to elevated privileges
  • Lateral Movement: Compromised environments can be used as pivot points for further attacks
  • Compliance Violations: Unauthorized code execution may violate regulatory requirements (HIPAA, PCI-DSS, etc.)

Severity Factors

The severity of this vulnerability varies based on:

  1. Input Control: Whether user input is involved in setting the prompt value
  2. Environment Sensitivity: The criticality of data processed in affected environments
  3. Privilege Level: The user account running the virtual environment
  4. Network Exposure: Whether the system is accessible to untrusted users
  5. Automation Level: How many virtual environments are created automatically

Who Is Most Vulnerable

Organizations at highest risk include:

  • SaaS Providers: Platforms offering Python execution environments to users
  • CI/CD-Heavy Organizations: Teams with extensive automation and dynamic environment creation
  • Shared Development Infrastructure: Companies with multi-tenant development servers
  • Research Institutions: Organizations running user-submitted code
  • DevOps Teams: Infrastructure teams managing large-scale Python deployments

How to Detect This Vulnerability

Monitoring Configuration Files

Implement file integrity monitoring for pyvenv.cfg files:

# Find all pyvenv.cfg files in your system
find / -name "pyvenv.cfg" -type f 2>/dev/null
# Monitor for changes
auditctl -w /path/to/venv/pyvenv.cfg -p wa -k venv_config_changes

Look for suspicious patterns:

  • Unexpected home values pointing outside standard Python installation directories
  • Multiple configuration lines that shouldn’t exist
  • Recent modifications to configuration files
  • home paths pointing to user directories or temporary locations

Code Analysis Techniques

Use static analysis to identify vulnerable patterns:

# Vulnerable pattern - direct user input to virtualenv
import subprocess
user_prompt = request.args.get('prompt')
subprocess.run(['python', '-m', 'virtualenv', f'--prompt={user_prompt}', 'venv'])
# Vulnerable pattern - environment variable without sanitization
os.environ['VIRTUALENV_PROMPT'] = branch_name
subprocess.run(['python', '-m', 'virtualenv', 'venv'])

Implement code scanning rules to detect:

  • Direct use of user input in virtualenv commands
  • Unsanitized environment variables passed to virtualenv
  • Missing input validation for prompt values

Log Indicators to Watch For

Monitor for these indicators of exploitation:

  • Unexpected Python interpreter paths in virtual environment configurations
  • Virtualenv creation with unusual prompt values containing special characters
  • Changes to pyvenv.cfg files outside of expected maintenance windows
  • Execution of Python code from non-standard interpreter locations
  • Failed imports or module loading errors suggesting interpreter redirection

Immediate Actions to Take

Step-by-step remediation checklist for addressing configuration injection vulnerabilities.
Step-by-step remediation checklist for addressing configuration injection vulnerabilities.

Apply Security Patches

Step 1: Update virtualenv immediately

# Upgrade to the latest patched version
pip install --upgrade virtualenv
# Verify the update
pip show virtualenv

The patched version modifies PyEnvCfg.write() to collapse line boundaries into spaces, preventing injection attacks.

Step 2: Verify the patch is applied

# Test that line injection is prevented
import subprocess
result = subprocess.run(
    ['python', '-m', 'virtualenv', '--prompt=test
home=/tmp', 'test_venv'],
    capture_output=True
)
# In patched version, the newline is converted to a space

Sanitize User Input

Implement input validation for all prompt values:

import re
def sanitize_prompt(prompt_value):
    """Remove line boundary characters from prompt values"""
    # Remove newlines, carriage returns, and other control characters
    sanitized = re.sub(r'[\r
\x00-\x1f]', '', prompt_value)
    # Limit length to prevent other attacks
    sanitized = sanitized[:50]
    # Allow only safe characters
    if not re.match(r'^[a-zA-Z0-9\-_\.]+$', sanitized):
        raise ValueError("Invalid prompt value")
    return sanitized
# Usage
try:
    safe_prompt = sanitize_prompt(user_input)
    os.system(f'python -m virtualenv --prompt={safe_prompt} venv')
except ValueError as e:
    # Handle invalid input
    log_security_event(f"Invalid prompt input rejected: {e}")

Harden Your Environment

Environment variable controls:

# Restrict who can set VIRTUALENV_PROMPT
# In /etc/security/limits.conf or similar
# Prevent unprivileged users from setting environment variables
# Use environment variable whitelisting in CI/CD
# Only allow specific, validated variables

File permissions:

# Restrict write access to virtual environment directories
chmod 750 /path/to/venv
chmod 640 /path/to/venv/pyvenv.cfg
# Ensure only authorized users can create virtual environments
setfacl -m u:developer:rx /path/to/venv

Long-Term Protection Strategies

Input Validation Best Practices

Establish comprehensive input validation policies:

  1. Whitelist Approach: Define allowed characters and patterns for prompt values
  2. Length Limits: Restrict prompt values to reasonable lengths (e.g., 50 characters)
  3. Type Checking: Ensure input matches expected data types
  4. Encoding Validation: Verify input uses expected character encoding
class PromptValidator:
    """Comprehensive prompt validation"""
    MAX_LENGTH = 50
    ALLOWED_PATTERN = r'^[a-zA-Z0-9\-_\.]+$'
    FORBIDDEN_CHARS = ['
', '\r', '\x00', '|', ';', '&', '$', '`']
    @classmethod
    def validate(cls, prompt):
        # Check length
        if len(prompt) > cls.MAX_LENGTH:
            raise ValueError("Prompt exceeds maximum length")
        # Check for forbidden characters
        if any(char in prompt for char in cls.FORBIDDEN_CHARS):
            raise ValueError("Prompt contains forbidden characters")
        # Check pattern
        if not re.match(cls.ALLOWED_PATTERN, prompt):
            raise ValueError("Prompt contains invalid characters")
        return prompt

Access Control in Shared Environments

Implement strict access controls:

  • User Isolation: Prevent users from accessing other users’ virtual environments
  • Directory Permissions: Use restrictive umask settings (e.g., umask 0077)
  • SELinux/AppArmor: Implement mandatory access controls
  • Container Isolation: Use containerization to isolate environments
# Set restrictive umask for virtual environment creation
umask 0077
python -m virtualenv venv
# Verify permissions
ls -la venv/pyvenv.cfg
# Should show: -rw------- (600)

Continuous Monitoring and Auditing

Establish ongoing security practices:

  1. Configuration Auditing: Regular reviews of pyvenv.cfg files
  2. Dependency Scanning: Monitor virtualenv for security updates
  3. Log Analysis: Automated analysis of virtualenv creation logs
  4. Penetration Testing: Regular testing of virtualenv usage in your environment
# Automated audit script
#!/bin/bash
echo "Auditing virtualenv configurations..."
find / -name "pyvenv.cfg" -type f 2>/dev/null | while read cfg; do
    echo "Checking: $cfg"
    # Check for suspicious home paths
    if grep -q "^home = " "$cfg"; then
        home_path=$(grep "^home = " "$cfg" | cut -d' ' -f3-)
        if [[ ! "$home_path" =~ ^/usr/bin/python|^/usr/local/bin/python ]]; then
            echo "WARNING: Suspicious home path in $cfg: $home_path"
        fi
    fi
    # Check for unexpected configuration lines
    line_count=$(wc -l < "$cfg")
    if [ "$line_count" -gt 10 ]; then
        echo "WARNING: Unusual number of configuration lines in $cfg"
    fi
done

Resources and Support

Official Documentation

  • virtualenv Official Repository: https://github.com/pypa/virtualenv
  • Python Virtual Environments Guide: https://docs.python.org/3/tutorial/venv.html
  • PEP 405 – Python Virtual Environments: https://www.python.org/dev/peps/pep-0405/

Security References

  • NIST Secure Software Development Framework: https://csrc.nist.gov/projects/secure-software-development-framework
  • OWASP Input Validation Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/InputValidationCheat_Sheet.html
  • CWE-94: Improper Control of Generation of Code: https://cwe.mitre.org/data/definitions/94.html

Getting Help

  • Report Security Issues: Contact the virtualenv security team through the official repository
  • Community Support: Python Security Interest Group (python-security@python.org)
  • Enterprise Support: Consult with your Python distribution provider (Red Hat, Canonical, etc.)

Frequently Asked Questions

Q: What is the main risk of this vulnerability?

A: Attackers can manipulate the pyvenv.cfg file to redirect the base interpreter path to a malicious location. This allows execution of untrusted code with the privileges of the user running the virtual environment, potentially leading to data theft, credential compromise, or system compromise.

Q: Which versions of virtualenv are vulnerable?

A: All versions using the PyEnvCfg.write() and PyEnvCfg._read_values() methods without proper line boundary sanitization are affected. This includes virtualenv 20.x and earlier. Check your version with pip show virtualenv and update immediately.

Q: How can attackers inject malicious configurations?

A: Through three primary vectors: the --prompt command-line option, the VIRTUALENV_PROMPT environment variable, or configuration files. By crafting input containing line boundary characters (newlines), attackers can add unauthorized configuration lines to the pyvenv.cfg file.

Q: What should I do immediately?

A: Take these steps in order: (1) Update virtualenv to the latest patched version, (2) Sanitize any user-supplied prompt values in your code, (3) Monitor your pyvenv.cfg files for unauthorized changes, (4) Review CI/CD pipelines for vulnerable patterns.

Q: Is this vulnerability exploitable in my CI/CD pipeline?

A: Yes, if your CI/CD pipeline sets VIRTUALENV_PROMPT using branch names, commit hashes, user identifiers, or other user-supplied data without sanitization. Review your pipeline configuration immediately and implement input validation.

Q: How do I verify if my systems are compromised?

A: Check pyvenv.cfg files for unexpected home values pointing outside standard Python installation directories, review recent configuration changes, audit environment variable settings, and check logs for unusual virtualenv creation patterns. Use the monitoring scripts provided in this advisory.

Q: Can this vulnerability be exploited remotely?

A: Direct remote exploitation requires the ability to influence virtualenv creation parameters. However, in web applications, CI/CD systems, or other automated environments that accept user input for prompt values, remote exploitation is possible.

Q: What’s the difference between this and other injection vulnerabilities?

A: This is a configuration injection vulnerability specific to the line-based format of pyvenv.cfg. Unlike command injection or code injection, it exploits the lack of escape syntax in the configuration file format, making it particularly difficult to defend against without proper input validation.

Q: Are virtual environments created before the patch applied still vulnerable?

A: No, the vulnerability exists in the creation process. However, if a malicious pyvenv.cfg was created before patching, it remains malicious. Audit existing virtual environments and recreate them with the patched version if necessary.

Q: How does this affect containerized environments?

A: In Docker and Kubernetes environments, if environment variables are dynamically injected based on user input, the vulnerability can be exploited. Implement the same input validation and sanitization practices in your container orchestration configurations.


Conclusion

The configuration injection vulnerability in virtualenv represents a significant risk to organizations using this tool for Python environment management. The vulnerability’s exploitability in CI/CD pipelines, shared development environments, and web applications makes it a priority for immediate remediation.

Organizations should prioritize updating virtualenv, implementing comprehensive input validation, and establishing ongoing monitoring practices. By following the guidance in this advisory, you can significantly reduce your exposure to this vulnerability and strengthen your overall Python security posture.

For questions or additional information, contact your security team or consult the official virtualenv security resources.


Document Version: 1.0
Last Updated: 2024
Classification: Security Advisory

← Back to IT Security