{"id":21429295,"url":"https://github.com/nystudio107/craft-twig-sandbox","last_synced_at":"2025-07-14T10:32:52.027Z","repository":{"id":246821070,"uuid":"822274961","full_name":"nystudio107/craft-twig-sandbox","owner":"nystudio107","description":"Allows you to easily create a sandboxed Twig environment where you can control what tags, filters, functions, and object methods/properties are allowed","archived":false,"fork":false,"pushed_at":"2024-10-01T20:01:02.000Z","size":65,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"develop-v5","last_synced_at":"2024-10-30T12:12:36.688Z","etag":null,"topics":["craftcms","sandbox","security","twig"],"latest_commit_sha":null,"homepage":"https://nystudio107.com/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nystudio107.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-30T19:23:58.000Z","updated_at":"2024-10-01T20:01:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"a2629741-14ca-4fa4-832d-917ac10df5fc","html_url":"https://github.com/nystudio107/craft-twig-sandbox","commit_stats":null,"previous_names":["khalwat/craft-twig-sandbox"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nystudio107%2Fcraft-twig-sandbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nystudio107%2Fcraft-twig-sandbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nystudio107%2Fcraft-twig-sandbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nystudio107%2Fcraft-twig-sandbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nystudio107","download_url":"https://codeload.github.com/nystudio107/craft-twig-sandbox/tar.gz/refs/heads/develop-v5","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225970889,"owners_count":17553411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["craftcms","sandbox","security","twig"],"created_at":"2024-11-22T22:16:41.407Z","updated_at":"2025-07-14T10:32:52.020Z","avatar_url":"https://github.com/nystudio107.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/badges/quality-score.png?b=v5)](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/?branch=develop) [![Code Coverage](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/badges/coverage.png?b=v5)](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/?branch=develop) [![Build Status](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/badges/build.png?b=v5)](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/build-status/develop) [![Code Intelligence Status](https://scrutinizer-ci.com/g/nystudio107/craft-twig-sandbox/badges/code-intelligence.svg?b=v5)](https://scrutinizer-ci.com/code-intelligence)\n\n# Craft Twig Sandbox\n\nAllows you to easily create a sandboxed Twig environment where you can control what tags, filters, functions, and object methods/properties are allowed\n\n## Requirements\n\nCraft Twig Sandbox requires Craft CMS 5.x\n\n## Installation\n\nTo install Craft Twig Sandbox, follow these steps:\n\n1. Open your terminal and go to your Craft project:\n\n        cd /path/to/project\n\n2. Then tell Composer to require the package:\n\n        composer require nystudio107/craft-twig-sandbox\n\n## About Craft Twig Sandbox\n\nRather than just creating a new Twig `Environment` for the sandbox, Craft Twig Sandbox sub-classes the Craft `View` class, which has a few benefits:\n\n* You get all of the Craft provided tags, filters, functions, objects, globals, etc. available to you if you want\n* Plugin-provided tags, filters, functions, and objects are available if you want\n* You get access to the familiar `.renderObjectTemplate()`, `.renderString()`, `.renderPageTemplate()` and `.renderTemplate()` methods\n* All of the normal Craft events and scaffolding related to template rendering are present as well\n\nIt also implements an `ErrorHandler` that sub-classes the Craft `ErrorHandler` which is used to handle exceptions that happen when rendering Twig templates. This allows you to optionally display exceptions such as:\n\n```\nTwig\\Sandbox\\SecurityNotAllowedFunctionError\nFunction \"dump\" is not allowed in \"__string_template__b0120324b463b0e0d2c2618b7c5ce3ba\" at line 1.\n```\n\n## Using Craft Twig Sandbox\n\nIn its simplest form, you can create a Twig Sandbox like so:\n\n```php\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$sandboxView = new SandboxView();\n```\n\nThis will create a new `SandboxView` that works just like the Craft web `View` class so you can use any of the `View` render methods for Twig templates:\n```php\n$result = $sandboxView-\u003erenderString();\n$result = $sandboxView-\u003erenderObjectTemplate();\n$result = $sandboxView-\u003erenderPageTemplate();\n$result = $sandboxView-\u003erenderTemplate();\n```\n\n...and they will be rendered using the default `BlacklistSecurityPolicy` so blacklisted Twig tags, filters, functions, and object methods/properties will not be allowed.\n\nIf any tags, filters, functions, or object methods/properties are used that are not allowed by the security policy, a `SecurityError` exception will be thrown.\n\n**N.B.:** For performance reasons, you should create a `SandboxView` once, and use it throughout your application's lifecycle, rather than re-creating it every time you want to render Twig using it.\n\n### Exception handling\n\nNote that in the above example, exceptions will be thrown if the security policy is violated; so you can handle the exception yourself if you like:\n\n```php\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\nuse Twig\\Sandbox\\SecurityError;\n\n$sandboxView = new SandboxView();\ntry {\n    $result = $sandboxView-\u003erenderTemplate();\n} catch (\\Throwable $e) {\n     // If this is a Twig Runtime exception, use the previous one instead\n     if ($e instanceof SecurityError \u0026\u0026 ($previousException = $e-\u003egetPrevious()) !== null) {\n         $e = $previousException;\n     }\n    // Exception handling here\n}\n```\n\nOr if you want to use Craft's default web/console exception handling when rendering templates, you can do that like this:\n\n```php\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$sandboxView = new SandboxView();\ntry {\n    $result = $sandboxView-\u003erenderTemplate();\n} catch (\\Throwable $e) {\n    $sandboxView-\u003esandboxErrorHandler-\u003ehandleException($e)\n}\n```\n\n...and the exception with a full stack trace will be displayed in the web browser, or in the console (depending on the type of the current request).\n\n### BlacklistSecurityPolicy\n\nThe `BlacklistSecurityPolicy` is a `SecurityPolicy` that specifies the Twig tags, filters, functions, and object methods/properties that **are not** allowed.\n\nIt defaults to [reasonable subset of blacklisted](https://github.com/nystudio107/craft-twig-sandbox/blob/develop-v5/src/twig/BlacklistSecurityPolicy.php#L19) Twig tags, filters, and functions, but you can customize it as you see fit:\n\n```php\nuse nystudio107\\crafttwigsandbox\\twig\\BlacklistSecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$securityPolicy = new BlacklistSecurityPolicy([\n   'twigTags' =\u003e ['import'],\n   'twigFilters' =\u003e ['base64_decode', 'base64_encode'],\n   'twigFunctions' =\u003e ['dump'],\n]);\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n$result = $sandboxView-\u003erenderString(\"{{ dump() }}\", []);\n```\n\nYou can also control what object methods and properties are allowed to be accessed. By default, the `BlacklistSecurityPolicy` does not restrict access to any object methods or properties.\n\nFor example, if you didn't want people to be able to access the `password` property of the `DbConfig` object via:\n\n```twig\n{{ craft.app.config.db.password }}\n```\nor\n```twig\n{{ craft.app.getConfig().getDb().password }}\n```\n...you would do:\n\n```php\nuse craft\\config\\DbConfig;\nuse nystudio107\\crafttwigsandbox\\twig\\BlacklistSecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$securityPolicy = new BlacklistSecurityPolicy([\n   'twigProperties' =\u003e [\n       DbConfig::class =\u003e ['password']\n   ],\n   'twigMethods' =\u003e [\n       DbConfig::class =\u003e ['getPassword']\n   ],\n]);\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n$result = $sandboxView-\u003erenderString(\"{{ craft.app.config.db.password }}\", []);\n```\n\nIf you don't want any properties or methods to be able to be accessed on a given object, you can pass in a `*` wildcard:\n\n```php\n   'twigProperties' =\u003e [\n       DbConfig::class =\u003e '*'\n   ],\n   'twigMethods' =\u003e [\n       DbConfig::class =\u003e '*'\n   ],\n```\n\n### WhitelistSecurityPolicy\n\nThe `WhitelistSecurityPolicy` is a `SecurityPolicy` that specifies the Twig tags, filters, functions, and object methods/properties that **are** allowed.\n\nIt defaults to [reasonable subset of whitelisted](https://github.com/nystudio107/craft-twig-sandbox/blob/develop-v5/src/twig/WhitelistSecurityPolicy.php#L19) Twig tags, filters, functions, and object methods/properties, but you can customize it as you see fit:\n\n```php\nuse nystudio107\\crafttwigsandbox\\twig\\WhitelistSecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$securityPolicy = new WhitelistSecurityPolicy([\n   'twigTags' =\u003e ['for', 'if'],\n   'twigFilters' =\u003e ['replace', 'sort'],\n   'twigFunctions' =\u003e ['date', 'random'],\n]);\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n$result = $sandboxView-\u003erenderString(\"{{ dump() }}\", []);\n```\n\nYou can also control what object methods and properties are allowed to be accessed. By default, the `WhitelistSecurityPolicy` restricts access to all object methods or properties.\n\nThat means you must explicitly specify each object property or method.\n\nFor example, if you wanted to grant access to:\n\n```twig\n{{ craft.app.config.general.devMode }}\n```\nor\n```twig\n{{ craft.app.getConfig().getGeneral().getDevMode() }}\n```\n...you would do:\n\n```php\nuse craft\\config\\GeneralConfig;\nuse craft\\services\\Config;\nuse craft\\web\\Application;\nuse craft\\web\\twig\\variables\\CraftVariable;\nuse nystudio107\\crafttwigsandbox\\twig\\WhitelistSecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$securityPolicy = new WhitelistSecurityPolicy([\n   'twigProperties' =\u003e [\n       CraftVariable::class =\u003e ['app'],\n       Application::class =\u003e ['config'],\n       Config::class =\u003e ['general'],\n       GeneralConfig::class =\u003e ['devMode'],\n   ]\n   'twigMethods' =\u003e [\n       Application::class =\u003e ['getConfig'],\n       Config::class =\u003e ['getGeneral'],\n   ],\n]);\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n$result = $sandboxView-\u003erenderString(\"{{ craft.app.config.general.devMode }}\", []);\n```\n\nIf you want all properties or methods to be able to be accessed on a given object, you can pass in a `*` wildcard:\n\n```php\n   'twigProperties' =\u003e [\n       DbConfig::class =\u003e '*'\n   ],\n   'twigMethods' =\u003e [\n       DbConfig::class =\u003e '*'\n   ],\n```\n\n### SecurityPolicy from a config file\n\nOften you'll want to provide a sane Twig sandbox, but also allow your users to add or remove from the policy as they see fit.\n\nTo make this easy to do, there is a `SecurityPolicy::createFromFile()` helper method to create a sandbox security policy from a config file:\n```php\n    public static function createFromFile(string $filePath, ?string $alias = null): BaseSecurityPolicy\n```\n\nYou pass it in a `$filePath`, and it will look for a file of that name (with `.php` added to the end of it) in the `craft/config/` directory. If no file is found, it will then also try to resolve the optional `$alias` and look for the file in that directory.\n\nIf the file still is not found, it will return a default `BlacklistSecurityPolicy`.\n\nThe config file is a standard [Yii2 Object Configuration file](https://www.yiiframework.com/doc/guide/2.0/en/concept-configurations).\n\nExample files you can copy \u0026 rename exists in the `craft-twig-standbox` codebase in `src/config/`, as `blacklist-sandbox.php` and `whitelist-sandbox-php`.\n\nThese are the default files that are used to create the respective security policies when you allocate a new `BlacklistSecurityPolicy` or `WhitelistSecurityPolicy`, and pass in no object configuration. \n\nSo for a practical example, the author of the SEOmatic plugin would copy the `config/blacklist-sandbox.php` file to that plugin's `src/` directory as `seomatic-sandbox.php`, and put in any customizations that they might want there.\n\nThen they could direct their users to copy the `seomatic-sandbox.php` file to their `craft/config/` directory if they wanted to make any customizations to it.\n\nThen to create the sandbox view in the plugin, they would do:\n\n```php\nuse nystudio107\\crafttwigsandbox\\helpers\\SecurityPolicy;\n\n$securityPolicy = SecurityPolicy::createFromFile('seomatic-sandbox', '@nystudio107/seomatic');\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n```\n\nThis will cause it to create the sandbox from the `seomatic-sandbox.php` file in the `craft/config/` directory (if it exists), and if it does not exist, it will load the config file from the `seomatic-sandbox.php` in the `@nystudio107/seomatic` directory (which points to the plugin's source).\n\nCraft automatically creates a namespaced alias for each plugin.\n\n### Custom SecurityPolicy\n\nYou can also create your own custom `SecurityPolicy` to use, it just needs to conform to the Twig [`SecurityPolicyInterface`](https://github.com/twigphp/Twig/blob/3.x/src/Sandbox/SecurityPolicyInterface.php):\n\n```php\nuse my\\custom\\SecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\n$securityPolicy = new SecurityPolicy([\n]);\n$sandboxView = new SandboxView(['securityPolicy' =\u003e $securityPolicy]);\n$result = $sandboxView-\u003erenderString(\"{{ dump() }}\", []);\n```\n\n### Adding a SandboxView via `config/app.php`\n\nIf you want to make a Twig sandbox available globally in your Craft application, you can add the following to your `config/app.php`:\n\n```php\nuse craft\\config\\DbConfig;\nuse nystudio107\\crafttwigsandbox\\twig\\BlacklistSecurityPolicy;\nuse nystudio107\\crafttwigsandbox\\web\\SandboxView;\n\nreturn [\n    // ...\n    'components' =\u003e [\n        'sandboxView' =\u003e [\n            'class' =\u003e SandboxView::class,\n            'securityPolicy' =\u003e new BlacklistSecurityPolicy([\n                'twigProperties' =\u003e [\n                    DbConfig::class =\u003e '*'\n                ],\n                'twigMethods' =\u003e [\n                    DbConfig::class =\u003e '*'\n                ],\n            ]),\n        ],\n    ],\n];\n```\n\nThis will create a globally available component that you can use via:\n```php\nCraft::$app-\u003esandboxView-\u003erenderString('{% set password = craft.app.getConfig().getDb().password(\"\") %}');\n```\n\nYou can even globally replace the default Craft `view` with a `SandboxView` if you want:\n\n```php\nreturn [\n    // ...\n    'components' =\u003e [\n        'view' =\u003e [\n            'class' =\u003e SandboxView::class,\n            'securityPolicy' =\u003e new BlacklistSecurityPolicy([\n                'twigProperties' =\u003e [\n                    DbConfig::class =\u003e '*'\n                ],\n                'twigMethods' =\u003e [\n                    DbConfig::class =\u003e '*'\n                ],\n            ]),\n        ],\n    ],\n];\n```\n\n## Craft Twig Sandbox Roadmap\n\nBrought to you by [nystudio107](https://nystudio107.com/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnystudio107%2Fcraft-twig-sandbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnystudio107%2Fcraft-twig-sandbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnystudio107%2Fcraft-twig-sandbox/lists"}