Output escaping PSR

263 views
Skip to first unread message

Chris Riley

unread,
Oct 4, 2016, 10:39:04 AM10/4/16
to PHP Framework Interoperability Group
Hi,

I think there could be quite some value in producing a spec and set of interfaces for consistent output escaping across frameworks. Security is an important consideration in every app and having a consistent API would make it much easier get it right.

Would like to hear peoples opinions on this and collect volunteers to join a working group.

~C

Korvin Szanto

unread,
Oct 4, 2016, 12:40:03 PM10/4/16
to PHP Framework Interoperability Group
Hi Chris,
Are you thinking like a text filter PSR or more of an output management PSR? It sounds like a single interface with a single method to me: `FilterInterface::filter($mixed): mixed;`.

Thanks,
Korvin

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/4c634f36-bd9c-43d2-a387-90a47f4dad84%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sara Golemon

unread,
Oct 4, 2016, 7:18:46 PM10/4/16
to PHP Framework Interoperability Group
On Tuesday, October 4, 2016 at 9:40:03 AM UTC-7, Korvin Szanto wrote:
Are you thinking like a text filter PSR or more of an output management PSR? It sounds like a single interface with a single method to me: `FilterInterface::filter($mixed): mixed;`.

There's many different forms of filtering:
* Pass filtering (removing of illegal sequences)
* Replacement filtering (transformation of illegal sequences with placeholders)
* Panic filtering (raise an exception on illegal sequences)
* Escaping (included because it's often conflated with filtering)

There are whitelist and blacklist variants of these.   There are also context sensitive issues for many of these; What's illegal in a JS context isn't the same as an HTML text context, or an HTML attribute context.

I don't know that we need standards for these permutations, but I imagine it's a little more than "single interface with a single method".

-Sara

Erik Landvall

unread,
Oct 5, 2016, 3:57:16 AM10/5/16
to PHP Framework Interoperability Group
I think it's a good idea. following..

Chris Riley

unread,
Oct 5, 2016, 7:44:00 AM10/5/16
to PHP Framework Interoperability Group
Hi,

My thinking was an output escaping spec. It is a lot more nuanced than you may initially think as there is context to consider eg you need to escape differently inside a html attribute as you do for straight onto the page, similarly for a js context or css context.

An interface containing a method per context could be one solution, it could also add a general purpose method eg escape($var, $context) al a PSR-3.

There is also complexity that may arise from different view implementations in different frameworks. Some use $this->method() to enable "view helpers" in otherwise raw html/php others are more complex and specify their own markup/extensions to php eg twig.

I would consider an ideal solution one which in-spite of all these differences allows a dev to intuitively figure out the right thing to do; if their framework of choice uses functions for view helpers they'd be able to guess that calling escape($var, CONTEXT_CSS) would do what they want, equally, if they had some sort of helper implementation $this->escapeCss($var) would work.

I'd like to see this PSR go slightly beyond just an interface and create a specification for frameworks to comply to with a minimal set of functionality, naming conventions and a specification which guarantees that a method/function does what you expect.

~C

Korvin Szanto

unread,
Oct 5, 2016, 12:05:33 PM10/5/16
to php...@googlegroups.com
Fair enough, until January my head is still in FIG 2.0 mode. I still would say that the examples you provide can fit into a single interface, but I do see that with FIG 3.0 our scope is probably a little bit different than lowest-common-denominator interface.
 
@Chris I like the idea so far. Escaping is certainly an issue we've had in concrete5 and it's something we've tried to solve in the past with mixed results. One thing that I'd say is it that this kind of filtering might go hand in hand with validation as well. 

Best wishes,
Korvin


-Sara

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Larry Garfield

unread,
Oct 5, 2016, 3:18:00 PM10/5/16
to php...@googlegroups.com
On 10/05/2016 05:05 PM, Korvin Szanto wrote:


On Tue, Oct 4, 2016 at 4:18 PM Sara Golemon <p...@golemon.com> wrote:
On Tuesday, October 4, 2016 at 9:40:03 AM UTC-7, Korvin Szanto wrote:
Are you thinking like a text filter PSR or more of an output management PSR? It sounds like a single interface with a single method to me: `FilterInterface::filter($mixed): mixed;`.

There's many different forms of filtering:
* Pass filtering (removing of illegal sequences)
* Replacement filtering (transformation of illegal sequences with placeholders)
* Panic filtering (raise an exception on illegal sequences)
* Escaping (included because it's often conflated with filtering)

There are whitelist and blacklist variants of these.   There are also context sensitive issues for many of these; What's illegal in a JS context isn't the same as an HTML text context, or an HTML attribute context.

I don't know that we need standards for these permutations, but I imagine it's a little more than "single interface with a single method".

Fair enough, until January my head is still in FIG 2.0 mode. I still would say that the examples you provide can fit into a single interface, but I do see that with FIG 3.0 our scope is probably a little bit different than lowest-common-denominator interface.
 
@Chris I like the idea so far. Escaping is certainly an issue we've had in concrete5 and it's something we've tried to solve in the past with mixed results. One thing that I'd say is it that this kind of filtering might go hand in hand with validation as well. 

I'm a bit skeptical here.  Such a standard would, it seems, need to dictate less an interface and more what happens when you want to escape for a given context.  How would that be realistically different than a universal implementation, which we usually try to avoid?

The audience I'd see for such a spec would be, essentially, template engine authors.  Vis, how would you make it easy to plug a given template engine (where escaping should happen) into an arbitrary framework (which provides an escaper)?  Or is the escaper part of the template engine itself, in which case it's about what the template syntax exposes to the user, which is... not what we usually target.

(PSR-3's equivalent question was much more straightforward; make a given library compatible with an arbitrary framework-provided logger, which was quite successful.  I'm not clear on what the equivalent is in this case.)

So I think the question to ask here would be: Fabien (Twig) and Taylor (Laravel's engine): what would help you in making your template engines more portable to other frameworks/applications in a secure fashion, if anything?

--Larry Garfield

Fabien Potencier

unread,
Oct 6, 2016, 12:57:10 AM10/6/16
to php...@googlegroups.com
Escaping would not make Twig more "portable" (whatever that means),
that's for sure.

To give some feedback from a project, Twig, that has an escaping
mechanism, you need to keep in mind that this is very performance
sensitive as it is potentially called hundred of times in a page. So,
this part of the code should be highly optimized (Twig only use one
function here, no abstraction, no classes, ... and we use some "tricks"
to make it run fast -- we do have a pull request about extracting this
code to make it reusable but it was never merged because of performance
concerns). So, Twig would not adopt a PSR with interfaces to implement
output escaping.

For those interested, you can have a look at our implementation here:
https://github.com/twigphp/Twig/blob/1.x/lib/Twig/Extension/Core.php#L977

Moreover, I don't see how such a PSR would make projects more
interoperable. What problems are we trying to fix here?

Fabien

>
> --Larry Garfield
>
> --
> You received this message because you are subscribed to the Google
> Groups "PHP Framework Interoperability Group" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to php-fig+u...@googlegroups.com
> <mailto:php-fig+u...@googlegroups.com>.
> To post to this group, send email to php...@googlegroups.com
> <mailto:php...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/3df62d34-af9d-c6b3-5595-07fd246ac8a5%40garfieldtech.com
> <https://groups.google.com/d/msgid/php-fig/3df62d34-af9d-c6b3-5595-07fd246ac8a5%40garfieldtech.com?utm_medium=email&utm_source=footer>.

Iain Cambridge

unread,
Oct 6, 2016, 3:34:29 AM10/6/16
to PHP Framework Interoperability Group
For me it seems like it would be wiser to have a PSR that would say use such and such method and we have a filtering method that we can trust and people can look and see if a project is using that method. 

Alessandro Lai

unread,
Oct 6, 2016, 3:53:05 AM10/6/16
to PHP Framework Interoperability Group
Maybe the aim of this PSR should be a test suite (or at least a data provider of common and edge cases for tests) instead of an interface: if your escaper pass all the tests, it's PSR-x compliant. 

This could be a really good standard, which any implementer can look up to to see if its implementation is up to the task.

Hari K T

unread,
Oct 6, 2016, 4:31:30 AM10/6/16
to php...@googlegroups.com

Maybe the aim of this PSR should be a test suite (or at least a data provider of common and edge cases for tests) instead of an interface: if your escaper pass all the tests, it's PSR-x compliant. 

This could be a really good standard, which any implementer can look up to to see if its implementation is up to the task.

Yes testbed is really nice to have.

Matteo Beccati

unread,
Oct 6, 2016, 4:45:47 AM10/6/16
to php...@googlegroups.com
Hi,

On 06/10/2016 09:53, Alessandro Lai wrote:
> Maybe the aim of this PSR should be a test suite (or at least a data
> provider of common and edge cases for tests) instead of an interface: if
> your escaper pass all the tests, it's PSR-x compliant.
>
> This could be a really good standard, which any implementer can look up
> to to see if its implementation is up to the task.

Still, I don't think it's a suitable goal for a PSR. We'd be defining
the output of an implementation, which is more or less like providing
one. What would be the benefit?


Cheers
--
Matteo Beccati

Development & Consulting - http://www.beccati.com/

David Négrier

unread,
Oct 6, 2016, 5:34:02 AM10/6/16
to PHP Framework Interoperability Group
Hey,

I would simply like to give a huge +1 to Larry's answer because he did nail the problem perfectly.

Escaping is done in the template, therefore is used by template engine authors. There are not a hundred different ways to do escaping and an escaping PSR would really dictate an implementation which is not what FIG is doing.

On the other end, there are huge interoperability issues at the template level. There are indeed a hundred different ways to write a template (Twig, Blade, Mustache, Smarty, pure PHP, you name it...), but all templates have in common that they take an array of parameters and that they spit out some HTML (or more precisely a string of content).

Therefore, IMHO, efforts to increase interoperability might be better focused it the template level rather than at the espcaping level.

For instance:

interface TemplateInterface
{
    public function render(array $parameters) : string;
}

Such an interface could be used to abstract template rendering from the actual implementation (think about rewriting all Smarty templates into Twig templates in a project without touching the PHP code base, just swapping the implementation of the template). Each template engine is internally in charge of the escaping so we don't need to focus on that.

++
David.

Woody Gilk

unread,
Oct 6, 2016, 8:15:04 AM10/6/16
to PHP Framework Interoperability Group

What if my templates use objects?


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--

David Négrier

unread,
Oct 6, 2016, 5:07:39 PM10/6/16
to PHP Framework Interoperability Group
Hey Woody,

I'm pretty sure there is a lot of things that need to be discussed if we go the template way.

The render method could be:

public function render(array|object $parameters) : string;

In that case, it would be up to the implementators to adapt to the passed parameter. This is mostly a solved problem with packages like symfony/property_access that let you access a property of whatever underlying object/array you have.
Or the interface could dictate that the parameters MUST be an array, in which case you could always wrap your object as a property of the parameters array:

$template->render(['obj'=>$myObject]);

Anyway, I'm sure there are a lot of things that can be discussed here. The render method could also return a PSR-7 ResponseInterface object or a strem instead of a string...
I don't want to dive deep into the details in this thread (mostly because it was initially about output escaping and I don't want to hijack too much the initial theme of the post) but I'd be interested in knowing if this approach has some support amongst the people reading this list.

What do you think?

++
David.

Geert Eltink

unread,
Oct 7, 2016, 1:58:17 AM10/7/16
to PHP Framework Interoperability Group
I don't think there should be a PSR to dictate how and if output is escaped. It also shouldn't dictate specific tests. If you are not sure about the security of a template engine output escape function there are better ways like a security audit and sending a PR with fixes or tests.

An escaping output PSR is pretty much useless since in the frameworks that I know they all use a template engine. If you want to do something useful you have to do it on the template engine level.

Because of my involvement with zend-expressive I know a bit about template engines and how to support multiple template engines.

If there is anything where you could apply an useful standard, it is the render interface. To get an idea have a look at this: https://github.com/zendframework/zend-expressive-template/blob/master/src/TemplateRendererInterface.php. This is basically the glue that makes Twig, Plates and zend-view compatible with zend-expressive. But having such an interface still doesn't dictate or guarantee consistent output escaping and security. 

Because of the differences between the engines and their template language, I think it's nearly impossible to enable output escaping by default (considering you don't want to make engines a lot slower).

Just my 2 cents,

Geert Eltink.
Reply all
Reply to author
Forward
0 new messages