2024-06-20 14:10:42 +00:00
< ? php
/*
* This file is part of Twig .
*
* ( c ) Fabien Potencier
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Twig\Sandbox ;
use Twig\Markup ;
use Twig\Template ;
/**
* Represents a security policy which need to be enforced when sandbox mode is enabled .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
final class SecurityPolicy implements SecurityPolicyInterface
{
private $allowedTags ;
private $allowedFilters ;
private $allowedMethods ;
private $allowedProperties ;
private $allowedFunctions ;
public function __construct ( array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = [])
{
$this -> allowedTags = $allowedTags ;
$this -> allowedFilters = $allowedFilters ;
$this -> setAllowedMethods ( $allowedMethods );
$this -> allowedProperties = $allowedProperties ;
$this -> allowedFunctions = $allowedFunctions ;
}
public function setAllowedTags ( array $tags ) : void
{
$this -> allowedTags = $tags ;
}
public function setAllowedFilters ( array $filters ) : void
{
$this -> allowedFilters = $filters ;
}
public function setAllowedMethods ( array $methods ) : void
{
$this -> allowedMethods = [];
foreach ( $methods as $class => $m ) {
2025-01-13 09:56:01 +00:00
$this -> allowedMethods [ $class ] = array_map ( 'strtolower' , \is_array ( $m ) ? $m : [ $m ]);
2024-06-20 14:10:42 +00:00
}
}
public function setAllowedProperties ( array $properties ) : void
{
$this -> allowedProperties = $properties ;
}
public function setAllowedFunctions ( array $functions ) : void
{
$this -> allowedFunctions = $functions ;
}
public function checkSecurity ( $tags , $filters , $functions ) : void
{
foreach ( $tags as $tag ) {
if ( ! \in_array ( $tag , $this -> allowedTags )) {
2025-01-13 09:56:01 +00:00
if ( 'extends' === $tag ) {
trigger_deprecation ( 'twig/twig' , '3.12' , 'The "extends" tag is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed.' );
} elseif ( 'use' === $tag ) {
trigger_deprecation ( 'twig/twig' , '3.12' , 'The "use" tag is always allowed in sandboxes, but won\'t be in 4.0, please enable it explicitly in your sandbox policy if needed.' );
} else {
throw new SecurityNotAllowedTagError ( \sprintf ( 'Tag "%s" is not allowed.' , $tag ), $tag );
}
2024-06-20 14:10:42 +00:00
}
}
foreach ( $filters as $filter ) {
if ( ! \in_array ( $filter , $this -> allowedFilters )) {
2024-09-05 17:51:48 +00:00
throw new SecurityNotAllowedFilterError ( \sprintf ( 'Filter "%s" is not allowed.' , $filter ), $filter );
2024-06-20 14:10:42 +00:00
}
}
foreach ( $functions as $function ) {
if ( ! \in_array ( $function , $this -> allowedFunctions )) {
2024-09-05 17:51:48 +00:00
throw new SecurityNotAllowedFunctionError ( \sprintf ( 'Function "%s" is not allowed.' , $function ), $function );
2024-06-20 14:10:42 +00:00
}
}
}
public function checkMethodAllowed ( $obj , $method ) : void
{
if ( $obj instanceof Template || $obj instanceof Markup ) {
return ;
}
$allowed = false ;
2025-01-13 09:56:01 +00:00
$method = strtolower ( $method );
2024-06-20 14:10:42 +00:00
foreach ( $this -> allowedMethods as $class => $methods ) {
if ( $obj instanceof $class && \in_array ( $method , $methods )) {
$allowed = true ;
break ;
}
}
if ( ! $allowed ) {
$class = \get_class ( $obj );
2024-09-05 17:51:48 +00:00
throw new SecurityNotAllowedMethodError ( \sprintf ( 'Calling "%s" method on a "%s" object is not allowed.' , $method , $class ), $class , $method );
2024-06-20 14:10:42 +00:00
}
}
public function checkPropertyAllowed ( $obj , $property ) : void
{
$allowed = false ;
foreach ( $this -> allowedProperties as $class => $properties ) {
if ( $obj instanceof $class && \in_array ( $property , \is_array ( $properties ) ? $properties : [ $properties ])) {
$allowed = true ;
break ;
}
}
if ( ! $allowed ) {
$class = \get_class ( $obj );
2024-09-05 17:51:48 +00:00
throw new SecurityNotAllowedPropertyError ( \sprintf ( 'Calling "%s" property on a "%s" object is not allowed.' , $property , $class ), $class , $property );
2024-06-20 14:10:42 +00:00
}
}
}