1

We're looking at allowing a way to embed custom code into a PHP application, and exploring secure/sandboxed ways to do that (e.g. if you've used Apex in Salesforce, or are familiar with ExpressionLanguage in Symfony, that kind of thing).

We're looking for a safe way to execute custom, user-supplied additional custom logic, but make sure it's restricted in that they can't supply e.g. code that executes dangerous filesystem commands.

What do I mean by "sandboxed"?

I want to allow untrusted, user-supplied code to execute.

e.g. we can't just allow someone to execute arbitrary PHP code, because they would have filesystem access and functions like exec(), file(), fopen(), etc. etc.

The nice thing about Twig is that the access given to users is extremely minimal. There's no functions you can use to e.g. access the file system or make HTTP calls.

What we're exploring

One thing we've exploring is allowing custom Twig to run, but the one downside to Twig is that it's really designed as a template language, so it's logic like this is sort of clunky because of all the extra brackets:

{% if foo.bar == 'test' %}
   {% for line in lines %}
      {% if line.rate > 10 %}
         ... more code here ... 
      {% endif %}
   {% endfor %}
{% endif %}

It would be much cleaner/easier if we could just write:

if foo.bar == 'test' 
{
   for line in lines {
      if line.rate > 10
      {
         ... more code here ...
      }
   }
}

Is it possible / has anyone seen Twig extended to support multiple lines of code, and not require all of the {% and %}?

Or failing that... has anyone seen any other option for safely embedding untrusted, user-supplied logic in a PHP app? We've also looked at the PHP Lua extension as a potential option, but I'm not sure how maintained it is...

3
  • You should explore the Token parser and Node documentation. However I'm unsure you'll be able to achieve what you want with the built-in "compliler" of Twig. You could also looks into altering the compiler, relevant documentation here Commented Dec 20, 2024 at 18:58
  • I think your question would be more clear if you could define "safely embedding". PHP itself can handle multiline logic blocks. How is it unsafe? What problem are you trying to solve? Commented Dec 21, 2024 at 8:26
  • @EatenbyaGrue I have added some clarity to the question above. By "sandboxing" I basically mean allowing untrusted, user-supplied code to run... but severely restricting what can be run so e.g. there's no filesystem access, etc. Commented Dec 23, 2024 at 12:38

1 Answer 1

0

It's hard to say without seeing your specific templates, but arguably, Twig templates shouldn't have logic in them -- that's kind of the point of an MVC design. If your templates are this complicated, then you should probably look at moving some of that code into the controller, rather than looking for a view layer tool that supports doing things that shouldn't be done in the view layer.

I think the solution in your case is simply to use smaller templates. For example, if the template is internally toggling between two different states:

{% if foo.bar == 'test' %}
   ... some large chunk
{% else %}
   ... some other large chunk
{% endif %}

Make two different templates, and conditionally render one of them:

$this->render($foo->bar === 'test' ? 'test.twig.html' : 'not_test.twig.html');

Or even:

$this->render($foo->bar . '.twig.html');

Also note, most if statements can be shortened to a ternary, and Twig supports shorthand ternaries, which makes this:

{% if line.rate > 10 %}
    {{ line.rate }}
{% endif %}

Into just this:

{{ line.rate > 10 ? line.rate }}

And if you have a large template chunk for each iteration of a loop, you can always pull the row template into its own partial:

{% for line in lines %}
{% include 'row_template.html.twig' %}
{% endfor %}
Sign up to request clarification or add additional context in comments.

1 Comment

The problem with moving this code into the controller, is that this is user-supplied code. It's not like part of the application, it's extra custom logic a user of the application may want to execute. So it's not really possible or appropriate to stick it into the controller.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.