PHPUnit: A Security Risk?

The author of PHPUnit was a bit surprised when he received a mail stating that PHPUnit was a security risk and hackers could remotely execute PHP code through a file named eval-stdin.php that ships used to ship with PHPUnit.

// eval-stdin.php
eval ('?>'. \file_get_contents('php://input'));

Even though the eval-stdin.php file itself indeed was vulnerable, it never should have been actively exploitable because:

  • PHPUnit is a dev dependency, and should never be installed in production.
  • One should never make their vendor folder publicly accessible. If it is placed in the wwwroot, use .htaccess or the like to prevent direct access to it.

Eventually a fix landed in PHPUnit, accompanied by this nice commit message:

This check should not be required ... yet here it is.

If you upload PHPUnit to a production webserver then your deployment process is broken.

If your vendor/ directory is publicly accessible on your webserver then your deployment process is broken.

*sigh*

PHPUnit: A Security Risk? →

Sharing PHP-CS-Fixer Rules Across Projects and Teams

Tim MacDonald shares a way to sharing PHP-CS-Fixer rules across your projects. It involves in setting up on repo/package that contains the rules and a little helper class that takes in a PhpCsFixer\Finder instance (along with optional extra rules).

<?php

namespace TiMacDonald;

use PhpCsFixer\Config;
use PhpCsFixer\Finder; 

function styles(Finder $finder, array $rules = []): Config {
  $rules = array_merge(require __DIR__.'/rules.php', $rules);

  return Config::create()
    ->setFinder($finder)
    ->setRiskyAllowed(true)
    ->setRules($rules);
}

Once required in your actual project – using Composer – you have that project’s .php_cs.dist call the styles function:

<?php

$finder = PhpCsFixer\Finder::create()
  ->in([
    __DIR__.'/app',
    __DIR__.'/config',
    __DIR__.'/database',
    __DIR__.'/routes',
    __DIR__.'/tests',
  ]);

return TiMacDonald\styles($finder);

Nice!

Sharing PHP-CS-Fixer Rules Across Projects and Teams →

Composer Inline Aliases: Fake a PHP Package Version by Aliasing a Specific Commit to it

Great tip by Mattias:

You can alias directly when requiring a package:

composer require monolog/monolog:"dev-bugfix as 1.0.x-dev"

Surely comes in handy when locally adjusting a library. More info on Inline Aliases in the Composer Documentation.

Laravel Valet not picking up php.ini changes, a fix

If you have Laravel Valet not picking up php.ini changes, try this:

Demystifying Dependency Injection Containers

Video from Kai Sassnowski’s talk at Laracon EU 2019:

The goal of this talk is to explain how dependency containers work by building our own. We start out by building the simplest DI container possible to demonstrate the underlying concept. Most people will be surprised about how little code this actually takes (3-4 effective lines of code). From there, we gradually add more sophisticated features like autowiring to create a container that more closely resembles what we are familiar with from Laravel. After listening to this talk, you will know how DI containers work at their core. You will also know how autowiring works and why it doesn’t work under certain circumstances.

PHP Performance Tip: Use fully-qualified function calls when working with namespaces

TIL: When working with namespaced files in PHP it’s a huge performance win when using fully-qualified function calls.

~

If you’re calling is_null in your code, PHP will first check for the function’s existence in the current namespace. If not found there, it will look for the function in the global namespace. This extra check is quite a drag, as detailed in this issue for the SCSS PHP Project.

If you do want to target PHP’s built-in is_null (or any other global function), it’s more performant to refer to it using it’s fully-qualified name, e.g. \is_null

❌ Slow:
is_null();

✅ Fast:
\is_null();

Alternatively you can also import the function first through a use statement.

✅ Fast:
use function is_null;
is_null();

~

In the case of SCSS PHP the change from is_null to \is_null lead to a 28% speed increase!. If you’re looking for more benchmarks, Toon Verwerft has done some benching in the past.

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Via this tweet that sparked my quest into knowing more about this.

Laravel 6 From Scratch Free Video Course

In this series, step by step, I’ll show you how to build web applications with Laravel 6. We’ll start with the basics and incrementally dig deeper and deeper, as we review real-life examples. Once complete, you should have all the tools you need. Let’s get to work!

All 68 videos in this course, totalling 8:59:43 hrs of material, are free to watch.

Laravel 6 From Scratch →

Convert between Symfony HttpFoundation Request / Response and Swoole Request / Response classes with swoole-http-message-bridge

Today I was implementing an HTTP Server using Swoole. At its core, the code looks just like the Swoole HTTP Server example:

<?php 
$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // …
    $response->end();
});

$http->start();

In that same project I was also looking to use a package that evolves around symfony/http-foundation which:

  1. Takes in a \Symfony\Component\HttpFoundation\Request instance
  2. Processes the $request to a \Symfony\Component\HttpFoundation\Response
  3. Returns the $response

Instead of adjusting the processor to work with the \Swoole\HTTP\Request and \Swoole\HTTP\Response classes, I looked into converting the \Swoole\HTTP classes to their \Symfony\Component\HttpFoundation counterparts. That way the processor itself would remain untouched, and only some translation before and after would be done.

~

My solution lay into the indragunawan/swoole-http-message-bridge package that provides just that. However, the package hadn’t been updated in two years and it was showing: It didn’t support symfony/http-foundation version 5. Above that builds were failing.

Luckily for me those errors were easily fixable, and the author was kind enough to merge my two Pull Requests (#3 and #4) in only a few hours time 🙂

<?php 

use Indragunawan\SwooleHttpMessageBridge\Symfony\Request as RequestFactory;
use Indragunawan\SwooleHttpMessageBridge\Symfony\Response as ResponseWriter;

$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // Convert the \Swoole\HTTP\Request instance into a \Symfony\Component\HttpFoundation\Request instance
    $sfRequest = RequestFactory::createFromSwooleRequest($request);

    // Process \Symfony\Component\HttpFoundation\Request, yielding a \Symfony\Component\HttpFoundation\Response
    $sfResponse = …;

    // Convert the \Symfony\Component\HttpFoundation\Response instance into a \Swoole\HTTP\Response instance and write it out to the client 
    ResponseWriter::writeSwooleResponse($response, $sfResponse);
});

$http->start();

Installation per Composer:

composer require indragunawan/swoole-http-message-bridge:^0.1.0

There’s a few more changes and additions that could be done to this package, but I’ll leave it at that for the time being 😉

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Azure Functions Custom Handlers

Baller addition (in preview) to Azure Functions:

Azure Functions offers first-class support for a limited number of languages. Now in preview, register custom handlers by providing a lightweight HTTP server in any desired language. Use this new capability to extend the language support for your applications, enabling the use of languages or language versions not provided by Azure Functions.

Upon receiving a request the Functions Host will proxy the call to Custom Handler’s Web Server, which can run any language. Its response will then be used as an output binding payload to the target.

Configuration of the Custom Handler happens using a host.json in the root to tell which process to run:

{
    "version": "2.0",
    "httpWorker": {
        "description": {
            "defaultExecutablePath": "node",
            "defaultWorkerPath": "server.js"
        }
    }
}

The contents of your function goes into its own directory. Your code is accompanied by a function.json in which you define the bindings that your function uses. You can bind to queueTrigger for example and output to a queue. HTTP of course is also supported, as per this example:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

It takes in the Request req and expects a Response res as output.

const express = require("express");
const app = express();

app.use(express.json());

const PORT = process.env.FUNCTIONS_HTTPWORKER_PORT;

const server = app.listen(PORT, "localhost", () => {
  console.log("Your port is ${PORT}");
  const { address: host, port } = server.address();
  console.log("Example app listening at http://${host}:${port}");
});

app.get("/hello", (req, res) => {
  res.json("Hello World!");
});

app.post("/hello", (req, res) => {
  res.json({ value: req.body });
});

What I’m currently missing in the documentation and examples repository though is an example using a Dockerfile to say, for example, run PHP code. On Twitter I found this example by Anthony Chu (PM Azure Functions):

The code itself is not available (as a repo) yet, but by looking at the screenshot you can get an idea of how it all comes together. Will do a follow-up post once example PHP code becomes available 😉

Azure Functions custom handlers →
Sample code for Azure Functions custom handlers (GitHub) →

Laraguard – Two Factor Authentication via TOTP for all your Users out-of-the-box.

Two Factor Authentication via TOTP for all your Users out-of-the-box.

This packages adds a Contract to detect in a per-user basis if it should use Two Factor Authentication. It includes a custom view and a listener to handle the Two Factor authentication itself during login attempts.

It is not invasive, but you can go full manual if you want.

To use it, add the TwoFactorAuthenticatable contract and the TwoFactorAuthentication trait to the User model, or any other model you want to make Two Factor Authentication available.

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use DarkGhostHunter\Laraguard\TwoFactorAuthentication;
use DarkGhostHunter\Laraguard\Contracts\TwoFactorAuthenticatable;

class User extends Authenticatable implements TwoFactorAuthenticatable
{
    use TwoFactorAuthentication;
    
    // ...
}

Installation per Composer:

composer require darkghosthunter/laraguard

Laraguard (GitHub) →
Laraguard Introdcutory Post (Medium) →

💵 This linked article is stuck behind Medium’s metered paywall, which may prevent you from reading it. Open the link in an incognito window to bypass Medium’s ridiculous reading limit.