Show HN: I built my own minimal PHP framework

9 points by aussieguy1234 ↗ HN
This is a simple PHP framework I built myself from scratch with minimal dependencies from composer. It has Autowiring DI and some simple routing provided by the Slim router.

The code: https://github.com/cipher-code/phpframework

10 comments

[ 3.1 ms ] story [ 29.8 ms ] thread
Little Bobby Tables' cousin Xavier S Scripts strikes again.

% wget -q -O- 'http://localhost:8080/hello/%3Cscript%3Ealert(%22oops%22)'

Hello, <script>alert("oops")

Nice one, this is not intended to provide security. You'll have to build that on top yourself. Its a lightweight bare bones framework after all.
I'd argue even a barebones framework should protect you against the most basic vulnerabilities, it's something Every Single App Ever will require.
That isn't how software security works unfortunately. Secure programming is not a layered service, it's a practice of ensuring each layer is secure in itself. Any software application is as secure as its weakest link.

i.e.:

<secure application logic>

<insecure framework foundation>

^ the above stack is not secure & adding more security on top won't change that.

---

All that said, the vuln above is in your example code & not in the framework itself, so at least there's that. However, I'd suggest one of two things:

(1) Securing just your example code is relatively easy - line 9 involves outputting unescaped data, also known as an "injection sink". This is one of the main things to avoid in writing secure code in general. Simply putting in some basic output escaping of any variables in output strings will fix this easily:

  return "Hello, ${htmlspecialchars($name)}";
(2) As a sibling commenter mentions, every single app ever will always require output escaping. So putting it into your framework as a feature will never be "bloat" - it will be used every time. This is for example why most PHP frameworks tend to use templating languages like Twig by default - Twig includes the above feature on-by-default, no need to do any escaping yourself. Adding something similar might be a good feature.
There are multiple approaches here. You could escape late like with htmlspecialchars(), or build it into the framework (recursively filter all POST/GET input for example). You can do it in the controller with filter_input etc...

But in the end, it doesn't need to be a part of the framework, I'd like to leave it up to the developers to decide on how it makes sense for them to do input filtering/output escaping based on their own requirements.

There are some cases where you wouldn't want to aggressively filter everything, for example I've worked on apps in the past that allow HTML for certain things. Turning on filtering would prevent that (although there are ways to allow/disallow certain tags).

> recursively filter all POST/GET input for example). You can do it in the controller with filter_input etc...

This is what many do and it's extremely bad practice. I wrote a pretty detailed comment here on HN explaining this before but can't find it easily now so here's a similar looking article I found instead: https://benhoyt.com/writings/dont-sanitize-do-escape/

it doesn't need to be a part of the framework, I'd like to leave it up to the developers

You're right, "need" is a strong word, it's a suggestion for a useful feature. Leaving it up to developers does in practice tend to lead to insecure code most of the time though: it can sometimes be nice to help developers write better apps.

If you need raw html output the best approach is to batch DOMSanitize it and cache it to be served raw: in these cases it's usually an exception so turning output escaping off for 1 or 2 exceptions isn't a huge ask (and focused the scope of your attack surface area when you're auditing).