Changing or bypassing accessibility is security-sensitive. For example, it has led in the past to the following vulnerability:

private methods were made private for a reason, and the same is true of every other visibility level. Altering or bypassing the accessibility of classes, methods, or fields violates the encapsulation principle and could introduce security holes.

This rule raises an issue when reflection is used to change the visibility of a class, method or field, and when it is used to directly update a field value.

Ask Yourself Whether

* You are at risk if you answered yes to those questions.

Recommended Secure Coding Practices

Don't change or bypass the accessibility of any method or field if possible.

If untrusted code can execute this method, make sure that it cannot decide which method or field's accessibility can be modified or bypassed.

Questionable Code Example

class MyClass
{
    public static $publicstatic = 'Static';
    private static $privatestatic = 'private Static';
    private $private = 'Private';
    private const CONST_PRIVATE = 'Private CONST';
    public $myfield = 42;

    private function __construct() {}
    private function privateMethod() {}
    public function __set($property, $value)  {}
    public function __get($property) {}
}

$clazz = new ReflectionClass('MyClass');

$clazz->getstaticProperties(); // Questionable. This gives access to private static properties

$clazz->setStaticPropertyValue('publicstatic', '42'); // OK as there is no overloading to bypass and it respects access control.
$clazz->getStaticPropertyValue('publicstatic'); // OK as there is no overloading to bypass and it respects access control.

// The following calls can access private or protected constants.
$clazz->getConstant('CONST_PRIVATE'); // Questionable.
$clazz->getConstants(); // Questionable.
$clazz->getReflectionConstant('CONST_PRIVATE'); // Questionable.
$clazz->getReflectionConstants(); // Questionable.

$obj = $clazz->newInstanceWithoutConstructor(); // Questionable. Bypassing private constructor.

$constructor = $clazz->getConstructor();
$constructorClosure = $constructor->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$constructor->setAccessible(true); // Questionable. Bypassing constructor accessibility.

$prop = new ReflectionProperty('MyClass', 'private');
$prop->setAccessible(true); // Questionable. Change accessibility of a property.
$prop->setValue($obj, "newValue"); // Questionable. Bypass of the __set method.
$prop->getValue($obj); // Questionable. Bypass of the __get method.

$prop2 = $clazz->getProperties()[2];
$prop2->setAccessible(true); // Questionable. Change accessibility of a property.
$prop2->setValue($obj, "newValue"); // Questionable. Bypass of the __set method.
$prop2->getValue($obj); // Questionable. Bypass of the __get method.

$meth = new ReflectionMethod('MyClass', 'privateMethod');
$clos = $meth->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$meth->setAccessible(true); // Questionable. Change accessibility of a method.

$meth2 = $clazz->getMethods()[0];
$clos2 = $meth2->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$meth2->setAccessible(true); // Questionable. Change accessibility of a method.

// Using a ReflectionObject instead of the class

$objr = new ReflectionObject($obj);
$objr->newInstanceWithoutConstructor(); // Questionable. Bypassing private constructor.

$objr->getStaticPropertyValue("publicstatic"); // OK as there is no overloading to bypass and it respects access control.
$objr->setStaticPropertyValue("publicstatic", "newValue"); // OK as there is no overloading to bypass and it respects access control.

$objr->getStaticProperties(); // Questionable. This gives access to private static properties

// The following calls can access private or protected constants.
$objr->getConstant('CONST_PRIVATE'); // Questionable.
$objr->getConstants(); // Questionable.
$objr->getReflectionConstant('CONST_PRIVATE'); // Questionable.
$objr->getReflectionConstants(); // Questionable.

$constructor = $objr->getConstructor();
$constructorClosure = $constructor->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$constructor->setAccessible(true); // Questionable. Bypassing constructor accessibility.

$prop3 = $objr->getProperty('private');
$prop3->setAccessible(true); // Questionable. Change accessibility of a property.
$prop3->setValue($obj, "newValue"); // Questionable. Bypass of the __set method.
$prop3->getValue($obj); // Questionable. Bypass of the __get method.

$prop4 = $objr->getProperties()[2];
$prop4->setAccessible(true); // Questionable. Change accessibility of a property.
$prop4->setValue($obj, "newValue"); // Questionable. Bypass of the __set method.
$prop4->getValue($obj); // Questionable. Bypass of the __get method.

$meth3 = $objr->getMethod('privateMethod');
$clos3 = $meth3->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$meth3->setAccessible(true); // Questionable. Change accessibility of a method.

$meth4 = $objr->getMethods()[0];
$clos4 = $meth4->getClosure($obj); // Questionable. It is possible to call private methods with closures.
$meth4->setAccessible(true); // Questionable. Change accessibility of a method.

See