Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![run-tests](https://github.com/protonemedia/laravel-xss-protection/actions/workflows/run-tests.yml/badge.svg)](https://github.com/protonemedia/laravel-xss-protection/actions/workflows/run-tests.yml)
[![Total Downloads](https://img.shields.io/packagist/dt/protonemedia/laravel-xss-protection.svg?style=flat-square)](https://packagist.org/packages/protonemedia/laravel-xss-protection)

Laravel Middleware to protect your app against Cross-site scripting (XSS). It sanitizes request input by utilising the [Security Core](https://github.com/GrahamCampbell/Security-Core) package, and it can sanatize [Blade echo statements](https://laravel.com/docs/8.x/blade#displaying-data) as well.
Laravel Middleware to protect your app against Cross-site scripting (XSS). It sanitizes request input by utilising the [voku/anti-xss](https://github.com/voku/anti-xss) package, and it can sanatize [Blade echo statements](https://laravel.com/docs/8.x/blade#displaying-data) as well. This package was inspired by the [Security Core](https://github.com/GrahamCampbell/Security-Core) package.

* PHP 8.2 and higher
* Laravel 10 and higher
Expand Down Expand Up @@ -106,7 +106,7 @@ Event::listen(function (MaliciousInputFound $event) {

### Additional configuration for `voku/anti-xss`

As of version 1.6.0, you may provide additional configuration for the `voku/anti-xss` package. You may do this by filling the `middleware.anti_xss` key. This is similar to the [Laravel Security](https://github.com/GrahamCampbell/Laravel-Security) package, which this package used to rely on.
As of version 1.6.0, you may provide additional configuration for the `voku/anti-xss` package. You may do this by filling the `middleware.anti_xss` key.

```php
'anti_xss' => [
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
],
"require": {
"php": "^8.2|^8.3|^8.4",
"graham-campbell/security-core": "^4.0",
"illuminate/contracts": "^10.0|^11.0|^12.0",
"spatie/laravel-package-tools": "^1.9.2"
"spatie/laravel-package-tools": "^1.9.2",
"voku/anti-xss": "~4.1.42",
"voku/portable-utf8": "^6.0.13"
},
"require-dev": {
"laravel/pint": "^1.14",
Expand Down
29 changes: 26 additions & 3 deletions src/Middleware/XssCleanInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace ProtoneMedia\LaravelXssProtection\Middleware;

use Closure;
use GrahamCampbell\SecurityCore\Security;
use Illuminate\Foundation\Http\Middleware\TransformsRequest;
use ProtoneMedia\LaravelXssProtection\Cleaners\BladeEchoes;
use ProtoneMedia\LaravelXssProtection\Events\MaliciousInputFound;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use voku\helper\AntiXSS;
use voku\helper\UTF8;

class XssCleanInput extends TransformsRequest
{
Expand Down Expand Up @@ -53,7 +54,7 @@ class XssCleanInput extends TransformsRequest
* @return void
*/
public function __construct(
protected Security $security,
protected AntiXSS $antiXss,
protected BladeEchoes $bladeEchoCleaner
) {
//
Expand Down Expand Up @@ -131,7 +132,11 @@ protected function transform($key, $value)
return null;
}

$output = $this->security->clean((string) $value);
$output = $this->antiXss->xss_clean((string) $value);

if ($this->antiXss->isXssFound() === false) {
$output = $this->cleanInvisibleCharacters($output);
}

if (! $this->enabledInConfig('allow_blade_echoes')) {
$output = $this->bladeEchoCleaner->clean((string) $output);
Expand Down Expand Up @@ -187,4 +192,22 @@ public static function clearCallbacks()

static::$skipKeyCallbacks = [];
}

/**
* Clean invisible characters from the input.
*
* @param string|array $input
*/
private function cleanInvisibleCharacters($input): string|array
{
if (is_array($input)) {
foreach ($input as $key => &$value) {
$value = $this->cleanInvisibleCharacters($value);
}

return $input;
}

return UTF8::remove_invisible_characters($input, true);
}
}
31 changes: 26 additions & 5 deletions src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

namespace ProtoneMedia\LaravelXssProtection;

use GrahamCampbell\SecurityCore\Security;
use ProtoneMedia\LaravelXssProtection\Middleware\XssCleanInput;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
use voku\helper\AntiXSS;

class ServiceProvider extends PackageServiceProvider
{
Expand All @@ -22,9 +23,29 @@ public function configurePackage(Package $package): void

public function packageBooted()
{
$this->app->singleton(Security::class, fn () => Security::create(
config('xss-protection.anti_xss.evil'),
config('xss-protection.anti_xss.replacement')
));
$this->app->when(XssCleanInput::class)
->needs(AntiXSS::class)
->give(function () {
$antiXss = new AntiXSS;

$replacement = config('xss-protection.anti_xss.replacement');

if ($replacement !== null) {
$antiXss->setReplacement($replacement);
}

$evil = config('xss-protection.anti_xss.evil');

if ($evil !== null) {
if (isset($evil['attributes']) || isset($evil['tags'])) {
$antiXss->addEvilAttributes($evil['attributes'] ?? []);
$antiXss->addEvilHtmlTags($evil['tags'] ?? []);
} else {
$antiXss->addEvilAttributes($evil);
}
}

return $antiXss;
});
}
}
Loading