PHPUnit INI Injection: How Newline Characters Enable RCE in CI/CD Pipelines

PHPUnit INI Injection: How Newline Characters Enable RCE in CI/CD Pipelines

A critical vulnerability in PHPUnit (GHSA-qrr6-mg7r-m243) exposes a subtle but devastating attack vector: newline injection in PHP INI values forwarded to child processes. This flaw allows attackers to execute arbitrary code by poisoning CI/CD pipelines where they control phpunit.xml configuration entries. For AI agent developers relying on PHP-based testing infrastructure, this represents a supply chain threat that can compromise entire deployment pipelines.

How the Attack Works

The vulnerability stems from PHPUnit's handling of PHP INI directives when spawning child processes. PHP configuration values containing newline characters (\n) are improperly sanitized, allowing attackers to inject additional PHP directives beyond what developers intended to set.

When PHPUnit forwards these values to child processes, the newline acts as a delimiter, effectively splitting a single configuration entry into multiple directives. An attacker who controls the phpunit.xml file can craft malicious INI values like:

<php>
    <ini name="memory_limit" value="128M\nauto_prepend_file=/tmp/shell.php"/>
</php>

This injects auto_prepend_file, causing PHP to execute arbitrary code before any legitimate script runs. Similar attacks work with extension (loading malicious shared libraries), disable_functions (removing security controls), or open_basedir bypasses.

Real-World Implications for AI Agent Deployments

AI agent systems frequently rely on PHP-based microservices, legacy integrations, or third-party tools that use PHPUnit for testing. The attack surface extends beyond direct PHPUnit usage:

  • Supply chain poisoning: Compromised dependencies can inject malicious INI values into test configurations
  • CI/CD compromise: Attackers gaining write access to repository files can persist RCE capabilities
  • Agent tool poisoning: MCP servers or agent tools that execute PHP subprocesses inherit the vulnerable configuration propagation

The risk amplifies in containerized environments where PHPUnit configurations are mounted as volumes or generated from environment variables. An attacker who compromises a CI secret can weaponize this vulnerability to maintain persistent access across rebuilds.

Defensive Measures for Agent Operators

Immediate mitigation requires sanitizing all PHP INI values before they reach PHPUnit:

import re
import subprocess

def sanitize_php_ini(value: str) -> str:
    """Remove control characters that could enable INI injection."""
    # Strip newlines, carriage returns, and null bytes
    sanitized = re.sub(r'[\r\n\x00]', '', value)
    return sanitized

def safe_phpunit_run(config_values: dict) -> subprocess.Popen:
    """Execute PHPUnit with sanitized INI values."""
    env = os.environ.copy()

    for key, value in config_values.items():
        # Apply sanitization before passing to PHP
        safe_value = sanitize_php_ini(value)
        env[f'PHP_{key}'] = safe_value

    return subprocess.Popen(
        ['phpunit'],
        env=env,
        # Additional hardening: restrict execution context
        cwd='/var/www/sandbox',
        user='phpunit-sandbox'
    )

For containerized deployments, implement defense in depth:

  1. Read-only filesystems: Mount /tmp and configuration directories as read-only where possible
  2. Network isolation: Run PHPUnit in isolated network namespaces without egress
  3. Capability dropping: Remove CAP_SYS_ADMIN, CAP_SETUID, and other dangerous capabilities from PHP test containers
  4. Input validation: Reject any phpunit.xml containing suspicious patterns like \n in ini values before execution

Verification and Monitoring

Audit existing configurations for injection patterns:

# Scan for suspicious INI values in phpunit.xml files
grep -r 'ini name.*value.*\\\\n' /path/to/test/configs/
grep -rE 'auto_prepend|extension.*=' /path/to/phpunit.xml

Monitor for anomalous PHP process spawning. Legitimate PHPUnit runs should never load unexpected extensions or prepend files outside the test directory.

Key Takeaways

This vulnerability demonstrates how seemingly innocuous configuration parsing can become an RCE vector when newlines aren't properly handled. For AI agent infrastructure, the lesson extends beyond PHP: any tool that forwards configuration to subprocesses needs rigorous input sanitization.

  • Patch PHPUnit to the latest version immediately
  • Audit CI/CD pipelines for unsanitized configuration injection points
  • Implement the sanitization wrapper shown above for any PHP-based agent tooling
  • Reference the original advisory at GHSA-qrr6-mg7r-m243 for version-specific guidance

AgentGuard360

Built for agents and humans. Comprehensive threat scanning, device hardening, and runtime protection. All without data leaving your machine.

Coming Soon