Latte a chystaný sandbox režim

David Grudl
Nette Core | 8129
+
+7
-

přesunuto z jiného vlákna

Doslechl jsem se, že někteří uživatelé potřebují sandbox režim, kde lze omezit, co všechno může autor šablony dělat: můžete omezit přístup jen k vybraným filtrům, proměnným, metodám, značkám a funkcím.

Hodí se k vykreslování „nedůvěryhodných“ šablon, které editují samotní uživatelé.

Sám jsem tomu nepřikládal nikdy důležitost, protože vycházím z toho, že při používání dependency injection může autor šablony dělat jen to, co mu dovolí objekty, které do ní programátor pošle. Pokud tedy hrozí nebezpeční, že by se koder přes $presenter->getContext()->getService('database')->query(...) dostával tam, kam nemá, jednoduše smažu proměnnou $presenter ze šablony. Ona je tam předaná jen pro případné užití autorem šablony, kvůli funkčnosti tam být nemusí. Respektive žádná z automaticky předávaných proměnných tam být nemusí.

Faktem ale je, že lze těžko zamezit volání delete() nad výsledkem z Nette Database Explorer. Nebo přístupu k monostate třídám, jako je dibi::query(...). A nebo všem systémovým PHP funkcím. Tak jsem oprášil neuvěřitelné 4 roky starý commit a sandbox režim mergnul.

API

Přístup řídí objekt implementující Latte\Policy:

interface Policy
{
	function isMacroAllowed(string $macro): bool;

	function isFilterAllowed(string $filter): bool;

	function isFunctionAllowed(string $function): bool;

	function isMethodAllowed(string $class, string $method): bool;

	function isPropertyAllowed(string $class, string $property): bool;
}

Z API by mohlo být patrné, co vše lze ovlivnit.

Výchozí implementace je třída Latte\Sandbox\SecurityPolicy má v základu všechno zakázané a jednotlivé věci je potřeba povolit:

$policy = new Latte\Sandbox\SecurityPolicy;
$latte->setPolicy($policy);

$policy->allowMacros(['=', 'foreach', 'block']);  // povolí {=$var} a tedy i {$var}, {foreach}, {block}
$policy->allowFilters($policy::ALL); // povolí všechny |filtry
$policy->allowFunctions(['trim', 'explode']); // povolí tyto globální funkce (a potažmo custom funkce)
$policy->allowMethods(DateTime::class, ['format']); // povolí volat tyto metody nad objekty DateTime
$policy->allowProperties(Nette\Database\Table\ActiveRow::class, $policy::ALL); // povolí přístup ke všem properties

Aktivace

Bezpečnostní pravidla se uplatní pro šablony, které se načtou novým makrem {sandbox untrustworthy.latte} (na rozdíl od {include ...}).

Pokud se mají pravidla použít už na první renderovanou šablonu, je potřeba to sdělit skrze: $latte->setSandboxMode();.

Potřeboval bych spolupráci od těch, kteří sandbox chtějí používat. Jak navrhnout co nejlépe třídu Latte\Sandbox\SecurityPolicy, co změnit, aby byla dobře použitelná, najít co nefunguje atd.