Cajón de arena

Latte tiene una fortaleza blindada directamente bajo el capó. Se llama modo sandbox y es una característica importante que protege las aplicaciones que utilizan plantillas de fuentes no confiables. Por ejemplo, cuando son editadas por los propios usuarios.

El modo sandbox se asegura de que la arena no salga de la caja. Así, proporciona acceso limitado a etiquetas, filtros, funciones, métodos, etc. ¿Cómo funciona? Simplemente definimos lo que queremos permitir en la plantilla. Al principio, todo está prohibido y poco a poco vamos concediendo permisos:

El siguiente código permite a la plantilla utilizar las etiquetas {block}, {if}, {else} y {=} (esta última es una etiqueta para imprimir una variable o expresión) y todos los filtros:

$policy = new Latte\Sandbox\SecurityPolicy;
$policy->allowTags(['block', 'if', 'else', '=']);
$policy->allowFilters($policy::All);

$latte->setPolicy($policy);

También podemos permitir el acceso a funciones globales, métodos o propiedades de objetos:

$policy->allowFunctions(['trim', 'strlen']);
$policy->allowMethods(Nette\Security\User::class, ['isLoggedIn', 'isAllowed']);
$policy->allowProperties(Nette\Database\Row::class, $policy::All);

¿No es increíble? Puedes controlarlo todo a un nivel muy bajo. Si la plantilla intenta llamar a una función no autorizada o acceder a un método o propiedad no autorizados, lanza la excepción Latte\SecurityViolationException.

Crear políticas desde cero, cuando todo está prohibido, puede no ser conveniente, así que puedes empezar desde una base segura:

$policy = Latte\Sandbox\SecurityPolicy::createSafePolicy();

Esto significa que todas las etiquetas estándar están permitidas excepto contentType, debugbreak, dump, extends, import, include, layout, php, sandbox, snippet, snippetArea, templatePrint, varPrint, widget. También se permiten todos los filtros estándar excepto datastream, noescape y nocheck. Por último, también se permite el acceso a los métodos y propiedades del objeto $iterator.

Las reglas se aplican a la plantilla que insertamos con la nueva etiqueta {sandbox} etiqueta. Que es algo así como {include}, pero activa el modo sandbox y además no pasa ninguna variable externa:

{sandbox 'untrusted.latte'}

Así, el diseño y las páginas individuales pueden utilizar todas las etiquetas y variables como antes, las restricciones se aplicarán sólo a la plantilla untrusted.latte.

Algunas infracciones, como el uso de una etiqueta o filtro prohibidos, se detectan en tiempo de compilación. Otras, como la llamada a métodos no permitidos de un objeto, en tiempo de ejecución. La plantilla también puede contener cualquier otro error. Para evitar que se lance una excepción desde la plantilla sandboxed, lo que interrumpe toda la renderización, puedes definir tu propio manejador de excepciones, que, por ejemplo, se limita a registrarla.

Si queremos activar el modo sandbox directamente para todas las plantillas, es fácil:

$latte->setSandboxMode();